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機制來加速回滾,
- 在日誌中記錄checkpoint_start (T1,T2…Tn) (Tx代表做checkpoint時,正在進行還未COMMIT的事務)
- 等待所有正在進行的事務(T1~Tn)COMMIT
- 在日誌中記錄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 政府改革-共和政體