崩潰復原與緩衝池 (WAL, ARIES & Buffer Pool)

★★★★Draft

FromDatabase Internals

📚 From the Books

崩潰復原與緩衝池 (WAL, ARIES & Buffer Pool)Storage Engines

儲存引擎要同時做到兩件互相拉扯的事:寫要快(所以把頁面改動先緩衝在記憶體裡批次刷回)、又斷電不能丟資料(所以每筆改動都得先落地)。緩衝池 (buffer pool) 負責前者,WAL 負責後者,ARIES 是斷電後把兩者兜回一致的演算法。

🧠 Intuition

TIP

資料庫活在兩層記憶體階層上:慢而持久的磁碟,快而易失的 RAM。緩衝池是「記憶體裡的頁面工作區」,WAL 是「先寫下來的流水帳」。規則只有一條:改頁之前,先把這筆改動寫進 log——這樣記憶體裡的工作區隨時可以在斷電後從 log 重建。

⚖️ Tradeoffs

緩衝池的頁面狀態:pinned / referenced / dirty
  • dirty(髒頁):被改過、與磁碟不同步,必須先刷回才能驅逐
  • referenced(已參照):正被某執行緒使用,用完要 dereference;使用中不該被驅逐。
  • pinned(釘住):明確要求不要驅逐。典型用法:B-Tree 越靠近根的節點幾乎每次查詢都命中,而高層節點數量只佔一小撮,把它們 pin 常駐記憶體,查一筆就只需為未快取的低層節點打磁碟,而非走滿 h 跳。
驅逐替換策略:從 FIFO 到 CLOCK / TinyLFU
  • FIFO:最早載入最先驅逐;不看後續存取,根節點最先載入卻最先變成候選——不實用。
  • LRU:重複存取就把該頁挪回佇列尾;但並行下更新指標、重接節點的代價高。衍生 2Q(分「最近」與「頻繁」兩佇列)、LRU-K(追蹤最近 K 次存取估存取時間)。
  • CLOCK / CLOCK-sweep:LRU 的緊湊、快取友善、可並行版本。環形緩衝配一個 access bit:存取設 1;掃描時 1→0 跳過、遇到 0 就成驅逐候選。指標與內容都能用 compare-and-swap 改,免額外鎖,Linux 用其變體。
  • TinyLFU:有時頻率最近性更能預測。用頻率直方圖維護緊湊歷史,分 Admission / Probation / Protected 三段。
  • ⚠️ Belady 異常:策略不理想時,增加快取頁數反而可能增加驅逐次數
WAL:write-ahead 規則與 LSN
  • WAL (Write-Ahead Log,又稱 commit log)僅追加、不可變的磁碟結構,所有寫入循序。
  • 核心規則:任何改動資料庫狀態的操作,都必須在對應頁面被改之前先寫進 log(write-ahead)——這正是緩衝池敢在記憶體裡緩衝改動的底氣。
  • 每筆記錄有唯一、單調遞增的 LSN (Log Sequence Number)。log 記錄先進日誌緩衝區 (log buffer),靠 force 刷到磁碟;一筆交易要等它的 commit 記錄 LSN 被 force 落地,才算真的提交
redo / undo 的表示:physical vs logical log
  • 狀態變更可用 before-image / after-image、或對應的 redo / undo 操作來記。
  • 物理日誌 (physical log):記完整頁面或逐位元組變更;邏輯日誌 (logical log):記操作本身(如「為 key Y 插入記錄 X」)。
  • 實務常混用:redo 用物理(加快復原)、undo 用邏輯(提高正常運行時的並行度)。
Steal / Force:緩衝池與 WAL 怎麼協調
  • Steal:允許在交易提交前,就刷回它改過的頁;No-steal:不准刷回任何未提交交易的頁。
  • Force:交易提交前,把它改過的頁全部刷回;No-force:允許提交時仍有頁沒刷回。
  • 取捨:No-steal 只靠 redo 就能復原,但需要較大的緩衝池;Force 復原時不必重建已提交結果,但提交較慢(多了 I/O)。通用原則不變:交易必須在 undo/redo 記錄寫進 log 之後,才能提交
ARIES:steal + no-force 的三階段復原
  • ARIESsteal / no-force 的復原演算法,用物理 redo(快)+邏輯 undo(並行度高)。斷電重啟走三階段:
    • ① 分析 (Analysis):從髒頁與進行中交易的資訊,定出 redo 的起點與待 undo 的交易清單。
    • ② 重做 (Redo)重放歷史到崩潰當下,把狀態拉回斷電前——不管交易是否已提交都先重放。
    • ③ 撤銷 (Undo):逆時間回滾所有未完成的交易,回到最後一致狀態。
  • 為防復原途中又斷電,undo 動作本身也會被記錄(即補償日誌記錄 CLR 的用途)。ARIES 靠 LSN 認記錄、用髒頁表追蹤進行中交易改過的頁、並搭配下面的模糊檢查點。
Checkpoint:讓 log 不必從頭重放
  • 檢查點標記「到此為止的記錄都已完全落地」,大幅縮短重啟時要重放的量。
  • 同步檢查點強制刷回所有髒頁——得暫停全部操作,不實用。
  • 模糊檢查點 (fuzzy checkpoint):以 begin_checkpoint / end_checkpoint 兩筆記錄夾住,頁面非同步刷回,完成後更新 last_checkpoint 指標,復原就從那裡開始。
  • 截斷 log:只有「對應的快取頁已刷回」的 log 記錄,才可以從 WAL 丟棄。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading