天天看點

lOracle教程之log buffer的記憶體結構

我們已經知道,日志緩沖區用來存放事務對資料塊的變化的日志資訊。那麼這裡的日志資訊到底包含哪些内容,是由哪些結構組成的呢?

Oracle記錄資料庫變化(也就是記錄日志資訊)的最小機關是改動向量(change vector)。改動向量用來描述對資料庫中任何單個資料塊所做的一次改動。改動向量的内容包括被改動的資料塊的版本号、事務操作代碼、被改動的資料塊的位址等。這裡的版本号非常重要,它能夠幫助資料塊始終能夠展現目前最新的狀态。Oracle在建立改動向量時,會從資料塊中複制其版本号。而當恢複期間,Oracle讀取改動向量并将改動應用于相應的資料塊以後,被恢複的資料塊的版本号加1。這裡的資料塊可以屬于表或資料索引,也可以屬于復原段。但是對于臨時表空間裡的臨時段,不會生成改動向量。

當多個改動向量按照先後順序組合在一起,進而完成對資料庫的一次改動時,Oracle稱這組改動向量為重做記錄(redo record)。重做記錄用來描述對資料庫的一個原子改動。所謂原子改動,就是說,當應用改動中的改動向量時,要麼全部成功,要麼全部失敗,不存在部分成功部分失敗的情況。重做記錄能夠幫助整個資料庫展現目前最新的狀态。

一個事務至少産生一個重做記錄,也可能産生多個重做記錄。而Oracle在應用日志記錄進行恢複的過程中,以事務作為恢複的最小機關。要麼恢複整個事務,要麼復原整個事務。也就是說,要麼運用事務重做記錄裡的所有改動向量,要麼一個改動向量都不運用。

是以,日志緩沖區就是許多重做記錄按照發生的先後順序組成的。同時,日志檔案也就是由許多重做記錄按照先後順序排列在一起而組成的檔案。

我們舉個執行個體來說明重做記錄和改動向量産生的過程。比如我們發出如下更新語句(假設表redo_test的NAME列上沒有建立索引):

SQL> select * from redo_test;

ID     NAME

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

1      abc

2      abc

SQL> update redo_test set name='cdf' where id=1;

該語句發出以後,會産生一個重做記錄,用來描述對表中資料塊進行的修改。包括下面三個改動向量。

  對復原段事務表的改動,這發生在復原段段頭。事務表中包含被修改的資料塊的位址、該事務的狀态(commit或active),以及存有該事務所使用的復原段的位址。如果事務表被修改,就會産生針對它的改動向量。

  對復原段資料塊的改動。将修改前的舊值(abc)存放到復原段的資料塊裡。這時復原段發生改變,于是産生改動向量。

  對redo_test表的資料塊所做的改動。将修改後的新值(cdf)存放到表的資料塊裡。這時資料塊發生改變,于是産生改動向量。

從這個過程可以看到,對于這個update事務,重做記錄中會有三個改動向量。當然可能還有其他情況會産生新的重做記錄,比如修改的列如果有索引,則必須修改索引。這時就會産生第二個重做記錄,用來描述對索引資料塊的修改。這時候的重做記錄還是和第一個重做記錄一樣,包含多個改動向量。此外,在事務完成之後運作commit或rollback語句時,就會産生第三個重做記錄。該重做記錄隻有一個改動向量,用來記錄對復原段事務表的更改,因為commit或rollback時,需要更新事務表裡記錄的該事務的狀态。