undo log與redo log原理分析

2013年了解事務日誌時寫的總結文章,最近在研究關係型資料庫,重新 review 一下,內容不一定準確,請指正。原文鏈接

資料庫通常藉助日誌來實現事務,常見的有undo log、redo log,undo/redo log都能保證事務特性,這裡主要是原子性和持久性,即事務相關的操作,要麼全做,要麼不做,並且修改的數據能得到持久化。

假設資料庫在操作時,按如下約定記錄日誌:

1. 事務開始時,記錄START T2. 事務修改時,記錄(T,x,v),說明事務T操作對象x,x的值為v 3. 事務結束時,記錄COMMIT T

undo log原理

undo log是把所有沒有COMMIT的事務回滾到事務開始前的狀態,系統崩潰時,可能有些事務還沒有COMMIT,在系統恢復時,這些沒有COMMIT的事務就需要藉助undo log來進行回滾。

使用undo log時,要求:

1. 記錄修改日誌時,(T,x,v)中v為x修改前的值,這樣才能藉助這條日誌來回滾;2. 事務提交後,必須在事務的所有修改(包括記錄的修改日誌)都持久化後才能寫COMMIT T日誌;這樣才能保證,宕機恢復時,已經COMMIT的事務的所有修改都已經持久化,不需要回滾。

使用undo log時事務執行順序

1. 記錄START T 2. 記錄需要修改的記錄的舊值(要求持久化)3. 根據事務的需要更新資料庫(要求持久化)4. 記錄COMMIT T

使用undo log進行宕機回滾

1. 掃描日誌,找出所有已經START,還沒有COMMIT的事務。2. 針對所有未COMMIT的日誌,根據redo log來進行回滾。

如果資料庫訪問很多,日誌量也會很大,宕機恢復時,回滾的工作量也就很大,為了加快回滾,可以通過checkpoint機制來加速回滾,

  1. 在日誌中記錄checkpoint_start (T1,T2…Tn) (Tx代表做checkpoint時,正在進行還未COMMIT的事務)
  2. 等待所有正在進行的事務(T1~Tn)COMMIT
  3. 在日誌中記錄checkpoint_end

藉助checkpoint來進行回滾

從後往前,掃描undo log1,如果先遇到checkpoint_start, 則將checkpoint_start之後的所有未提交的事務進行回滾;2. 如果先遇到checkpoint_end, 則將前一個checkpoint_start之後所有未提交的事務進行回滾;(在checkpoint的過程中,可能有很多新的事務START或者COMMIT)。

使用undo log,在寫COMMIT日誌時,要求redo log以及事務的所有修改都必須已經持久化,這種做法通常很影響性能。

redo log原理

redo log是指在回放日誌的時候把已經COMMIT的事務重做一遍,對於沒有commit的事務按照abort處理,不進行任何操作。

使用redo log時,要求:

1. 記錄redo log時,(T,x,v)中的v必須是x修改後的值,否則不能通過redo log來恢復已經COMMIT的事務。2. 寫COMMIT T日誌之前,事務的修改不能進行持久化,否則恢復時,對於未COMMIT的操作,可能有數據已經修改,但重放redo log不會對該事務做任何處理,從而不能保證事務的原子性。

使用redo log時事務執行順序

1. 記錄START T2. 記錄事務需要修改記錄的新值(要求持久化)3. 記錄COMMIT T(要求持久化)4. 將事務相關的修改寫入資料庫

使用redo log重做事務

1. 掃描日誌,找到所有已經COMMIT的事務;2. 對於已經COMMIT的事務,根據redo log重做事務;

在日誌中使用checkpoint

1. 在日誌中記錄checkpoint_start (T1,T2...Tn) (Tx代表做checkpoint時,正在進行還未COMMIT的日誌)2. 將所有已提交的事務的更改進行持久化;3. 在日誌中記錄checkpoint_end

根據checkpoint來加速恢復

從後往前,掃描redo log1,如果先遇到checkpoint_start, 則把T1~Tn以及checkpoint_start之後的所有已經COMMIT的事務進行重做;2. 如果先遇到checkpoint_end, 則T1~Tn以及前一個checkpoint_start之後所有已經COMMIT的事務進行重做;

與undo log類似,在使用時對持久化以及事務操作順序的要求都比較高,可以將兩者結合起來使用,在恢復時,對於已經COMMIT的事務使用redo log進行重做,對於沒有COMMIT的事務,使用undo log進行回滾。redo/undo log結合起來使用時,要求同時記錄操作修改前和修改後的值,如(T,x,v,w),v為x修改前的值,w為x修改後的值,具體操作順序為:

1. 記錄START T2. 記錄修改日誌(T,x,v,w)(要求持久化,其中v用於undo,w用於redo)3. 更新資料庫4. 記錄 COMMIT T

4和3的操作順序沒有嚴格要求,並且都不要求持久化;因為如果宕機時4已經持久化,則恢復時可通過redo log來重做;如果宕機時4未持久化,則恢復時可通過undo log來回滾;在處理checkpoint時,可採用與redo log相同的處理方式。


推薦閱讀:

#A09-訓練日誌02/08-02/11  硬拉到爆炸174kg
PgSQL · 內核解析 · 同步流複製實現分析
Stellaris開發日誌#108 | 3/15 2.0版本號發布後支持(第一部分)
鋼鐵雄心4開發日誌 | 3/15 1.5.1 版本號測試補丁更新(新增內容)
歐陸風雲4開發日誌 | 4/10 政府改革-共和政體

TAG:關係資料庫 | MySQL | 日誌 |