首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

數據庫恢復機制深度解析:日誌、檢查點、影子分頁與並發恢復

     編輯:DB2 教學

數據庫恢復機制深度解析

數據庫系統的核心承諾是「數據不丟、狀態一致」。當事務失敗、系統崩潰甚至磁盤損壞發生時,恢復子系統必須將數據庫從不一致狀態還原到一致狀態。本文系統梳理恢復的基本概念、存儲模型、基於日誌的兩大策略(推遲/立即修改)、檢查點優化、影子分頁、並發事務恢復以及緩存管理,助你構建完整的恢復知識體系。

一、恢復的基本概念與失敗分類

恢復的本質是利用冗余(物理冗余,如日誌、備份)將數據庫從失敗導致的不一致狀態恢復到一致狀態。常見失敗類型:

  • 事務失敗:邏輯錯誤(如完整性約束違反)或系統錯誤(如死鎖被選為受害者)。
  • 系統崩潰:斷電、硬件故障、OS 崩潰。假設非易失性存儲(磁盤)不受影響。
  • 磁盤失敗:磁盤壞道、控制器故障。假設可通過校驗機制檢測。

恢復策略分兩階段:正常運行時記錄足夠信息,失敗發生時利用信息還原。

二、存儲結構與數據訪問模型

為了精確描述恢復過程,引入分層存儲模型:

層級名稱特性
L1易失性存儲器主存、Cache,斷電丟失
L2非易失性存儲器磁盤、閃存、NVRAM,斷電保留
L3穩定存儲器理想模型,任何失敗不丟數據(如 RAID、異地備份)

數據在層間流動的四種基本操作:

  • input(A):磁盤物理塊 → 主存緩沖塊
  • output(A):主存緩沖塊 → 磁盤物理塊
  • read(X):主存緩沖塊 → 事務私有工作區
  • write(X):事務私有工作區 → 主存緩沖塊

注意:DBMS 不必每次 write 都調用 output,寫回策略由 OS 決定(如延遲寫回)。

三、基於日誌的恢復:兩大核心策略

日誌記錄格式(存放於穩定存儲器):

  • <Ti, start>:事務開始
  • <Ti, X, old_value, new_value>:寫操作
  • <Ti, commit>:事務提交

假設同一時刻最多一個活躍事務(單事務場景)。

1. 推遲數據庫修改

  • 事務執行期間不修改數據庫,僅記錄日誌;
  • 達到 partially committed 狀態(即將提交)時才將修改 write 到數據庫;
  • 恢復規則:無 <Ti, commit> → 無操作;有 <Ti, commit> → 順序 redo(重做,寫入 new_value)。
  • 此模式下 old_value 其實可不記錄。

2. 立即數據庫修改

  • 事務未提交前即允許修改數據庫(write 到主存);
  • 必須遵守 WAL 規則:日誌記錄必須先於對應數據頁寫入磁盤(log force);
  • 恢復規則:無 <Ti, commit> → 逆序 undo(撤銷,寫回 old_value);有 <Ti, commit> → 順序 redo。

3. 檢查點優化

遍歷整個日誌開銷極大,引入 <checkpoint>:

  1. 周期性將所有已提交事務的修改從主存 output 到磁盤;
  2. 在日誌中寫入 <checkpoint> 記錄(可能有未提交事務正在進行)。

恢復時:反向掃描日誌找到最近的 <checkpoint>,再繼續反向找到最近一個未提交事務的 <Ti, start>,從該處開始執行 redo/undo。

示例時序圖(立即修改模式):

檢查點恢復時序圖

失敗發生時:T1 已在檢查點前提交 → 忽略;T2、T3 已提交但未 output → redo;T4 未提交 → undo。

四、影子分頁:另一種恢復路徑

假設:單活躍事務、磁盤不失敗、db_pointer 始終指向一致性副本。

  • 事務在影子拷貝上修改;
  • 提交時將影子拷貝寫入磁盤並原子更新 db_pointer;
  • 失敗時直接拋棄影子拷貝,db_pointer 仍指向舊一致副本。

缺點:大型數據庫拷貝整個頁面開銷極大,難以應用於並發場景。

五、並發事務的恢復

擴展假設:共享緩沖池、共享日誌、嚴格兩階段鎖(2PL)保證隔離性、日誌記錄交織、檢查點記錄活躍事務列表 <checkpoint, L>。

恢復算法:

  1. 初始化 undo_list、redo_list 為空;
  2. 反向掃描日誌找到最近的 <checkpoint, L>;
  3. 對 L 中每個事務:按日誌逆序將 update 加入 undo_list,正序加入 redo_list;
  4. 執行 undo_list 再執行 redo_list。

六、緩存管理:日誌緩存與數據庫緩存

1. 日誌緩存

  • 日誌先寫入主存緩存,緩存滿或執行 log force 時批量 output 到磁盤(減少 I/O);
  • 三大鐵律:順序寫入、<Ti, commit> 落盤前不可進入 Committed 狀態、日誌先於數據頁落盤(WAL)。

2. 數據庫緩存

  • 以頁(塊)為單位管理;緩存滿時按置換策略(如 LRU)淘汰頁,若被修改則先 output;
  • 與日誌緩存「整體寫回」不同,數據庫緩存是「按頁獨立置換」。

七、非易失性存儲器失敗的恢復

引入 dump 操作:定期將數據庫完整備份到更低層級的穩定存儲(如磁帶)。恢復時先恢復最近一次 dump,再重放其後的日誌。這是分層存儲思想在災難恢復中的延伸應用。

總結

數據庫恢復是一個「以冗余換可靠」的系統工程:日誌是核心數據結構,WAL是核心協議,檢查點是核心優化,undo/redo是核心操作。理解單事務到並發、從主存到磁盤的層層遞進,才能在架構設計與故障排查時游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved