天天看點

Oracle教程之log buffer的内部管理機制

日志緩沖區的内部管理分為兩部分,一部分是生成重做記錄,另一部分就是重做記錄寫入聯機日志檔案。這兩部分不是孤立的,沒有關聯的。在生成重做記錄的過程中,可能會觸發LGWR将重做記錄寫入聯機日志檔案。

我們先用一個例子來說明在日志緩沖區中的操作過程,并使用[file# , blk#]來表示某個資料塊;file#表示檔案号;blk#表示資料塊号。

假設session 1發出更新語句:update redo_test set name='cdf' where id=1;

Oracle首先找出id=1所在的資料塊(假設為[file#4,blk#120])放入buffer cache,然後找出一個可用的復原段資料塊(假設為[file#2,blk#19]),将舊值'abc'放入該塊,同時生成重做記錄。然後将'cdf'放入表的資料塊,再生成重做記錄。這時日志緩沖區的結構可以簡單地表示為下面的形式(我們在前面描述日志緩沖區的記憶體結構時,知道重做記錄中最重要的就下面列的這幾列内容。同時,下面的一行就表示一個重做記錄):

行号  事務id file#  block# row  column  value

1  T1  2       19  -  -   abc

2  T1  4       120  1  2   cdf

這時假設session 2發出其他更新語句:update t set c1=10 where c1=9;

同樣的道理,Oracle找到該資料塊(假設為[file#5,blk#200])放入buffer cache,并找到復原段資料塊(假設為[file#2,blk#30])存放舊值,生成重做記錄,更新表的資料塊,再次生成重做記錄。這時日志緩沖區的結構類似如下形式:

3  T20  2       30  -  -   9

4  T20  5       200  20  1   10

這時,session 1又發出更新語句:update redo_test set name='xyz1' where id=2,并送出(commit)。同樣的方式處理復原段和資料塊,并生成重做記錄。假設這時生成日志緩沖區為:

5  T1  2       19  -  -   abc

6  T1  4       120  2  2   xyz1

7  T1  commit  SCN  timestamp

這時我們可以注意到,送出标記也被記錄到了重做記錄中。每次送出時,都會生成一個SCN号,SCN号越小,說明發生得越早,其所屬的重做記錄就越排在前面。一旦使用者發出commit語句,系統就會觸發LGWR程序。這時,LGWR程序會将上面所顯示的所有重做記錄都寫入聯機日志檔案中。注意,其中也包括尚未送出的事務T20。

SCN号就是Oracle資料庫内部的原子鐘,可以認為是精确到秒後9位小數的時間資訊。SCN号記錄了資料庫内部各個事件發生的先後順序,比如DML、commit、DBWn寫髒塊等都會引起SCN号的增加。

在LGWR寫這些重做記錄的過程中,又有其他session 發出更新語句,并送出。這時的日志緩沖區假設如下所示:

以上的重做日志正在由LGWR寫入, 在LGWR寫時生成以下的重做日志

-----------------------------------------------------

8  T20  2   39  -  -   289 

9  T20  5   498  220  3   190

10  T9  2   90  -  -   hhh

11  T9  9   100  20  9   xxx

12  T9  commit   SCN  timestamp

13  T18  2   189  -  -   18

14  T18  10   29  300  10   20

15  T18  commit   SCN  timestamp

當LGWR寫完第一批重做記錄(第1到第7行)以後,就會立即開始寫第二批重做記錄(第8行到第15行)。注意,第二批重做記錄中,存在兩個commit,但LGWR不會分成兩次來寫,而是一次就将它們全部寫入。當LGWR在寫完第1到第7行的改動向量以後,這部分的日志緩沖區記憶體就被釋放了,可以被新生成的重做記錄所覆寫。