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

InnoDB 核心機制深度解析:Redo Log、Undo Log、Checkpoint 與崩潰恢復原理

     編輯:MySQL 綜合教學

InnoDB 核心機制深度解析:Redo Log、Undo Log、Checkpoint 與崩潰恢復原理

InnoDB 透過 Redo Log(重做日誌) 保證事務持久性,Undo Log(回滾日誌) 保證原子性與 MVCC。本文從 LSN、髒頁、WAL、Checkpoint、崩潰恢復等核心概念切入,系統闡述其運作原理、配置調優與故障排查。

一、核心概念速覽

1. LSN (Log Sequence Number)

  • 無符號 64 位整數,單調遞增,代表日誌字節偏移量。
  • 每個頁面、Redo Log、Checkpoint 都有 LSN,通過 LSN 定位日誌位置、判斷頁面是否需恢復。
  • 查看:SHOW ENGINE INNODB STATUS 中的 LOG 區塊。

2. 髒頁

  • Buffer Pool 中被修改但未刷盤的頁面。
  • Flush List:各 Buffer Pool Instance 維護,按修改 LSN 排序,最老頁面(最小 LSN)優先刷盤。
  • 刷盤觸發條件:
    1. Redo Log 循環寫滿(需推進 Checkpoint)
    2. Buffer Pool 空間不足需淘汰髒頁
    3. 系統空閒時後台線程定期刷新
    4. Checkpoint 觸發
  • 關鍵參數:innodb_max_dirty_pages_pct (預設 90%) 控制髒頁比例上限。

3. WAL (Write-Ahead Logging)

「日誌先行」:事務提交前,Redo Log 必須持久化;數據頁面可延遲刷盤。兼顧持久性與效能。

二、Undo Log:原子性與 MVCC 基石

儲存位置

  • 預設在系統表空間 ibdata1。
  • 5.6+ 支援獨立 Undo 表空間(innodb_undo_tablespaces、innodb_undo_directory)。

分類

  • Insert Undo:僅事務本身可見,提交後即可丟棄。
  • Update Undo:UPDATE/DELETE 產生,需維護多版本鏈,支援 MVCC 讀取歷史版本。

版本鏈遍歷

舊事務讀取時順著 Undo 鏈尋找可見版本。鏈過長(長事務未提交、大量更新)會導致讀取效能下降(參考 Bug #69812)。

三、Redo Log:持久性保障

檔案結構

  • ib_logfile0, ib_logfile1 ... 循環寫入。
  • 總大小 = innodb_log_files_in_group × innodb_log_file_size。
  • 目錄由 innodb_log_group_home_dir 控制。

寫入機制

  1. 用戶線程生成 Redo 記錄寫入 Log Buffer(記憶體)。
  2. LGWR (Log Writer) 觸發條件將 Buffer 刷盤:
    • 事務提交(受 innodb_flush_log_at_trx_commit 控制)
    • Log Buffer 使用量達 1/2(舊版 1/3)
    • 每秒定時刷新
    • Checkpoint 需要
  3. 順序寫入,IO 效能高。
  4. 關鍵參數 innodb_flush_log_at_trx_commit

    值行為持久性效能
    1 (預設)每次提交 fsync 刷盤最強(不丟事務)最低
    2提交寫 OS Cache,每秒 fsync最多丟 1 秒事務高
    0不主動刷盤,靠後台每秒 fsync掛掉可能丟事務最高

    四、Checkpoint:推進恢復起點

    定期將「已刷盤的最老髒頁 LSN」記錄為 Checkpoint,恢復時只需重放 Checkpoint 之後的 Redo Log。

    四類 Checkpoint

    1. Sharp Checkpoint:正常關庫時,刷新所有髒頁,LSN 推進到最新。
    2. Master Thread Checkpoint:後台線程每秒/每 10 秒異步刷新部分髒頁(1.2+ 移至 Page Cleaner 線程)。
    3. FLUSH_LRU_LIST Checkpoint:LRU 末尾淘汰髒頁時強制刷盤(1.2+ 異步化)。
    4. Async/Sync Flush Checkpoint:Redo Log 空間不足(超 76% 未 Checkpoint)觸發強制刷髒頁,可能阻塞用戶線程(1.2+ 異步化)。
    5. Dirty Page Too Much Checkpoint:髒頁比例超 innodb_max_dirty_pages_pct 強制刷盤。

    五、崩潰恢復流程

    1. 讀取最新 Checkpoint LSN。
    2. Redo 階段:從 Checkpoint LSN 開始正向掃描 Redo Log,重放所有已提交事務的修改(Rolling Forward)。
    3. Undo 階段:識別未提交事務(有 BEGIN 無 COMMIT),利用 Undo Log 反向回滾其修改(Rolling Back)。

    得益於 LSN 有序性,InnoDB 僅需處理增量日誌,恢復速度快。

    六、Log Buffer 與 IO 優化

    • innodb_log_buffer_size:預設 8MB~64MB(視版本)。大事務系統可調大至 64MB~256MB,減少 LGWR 喚醒頻率。
    • 批量提交:將多條 DML 合併為一個事務,減少 fsync 次數。
    • 大量載入:SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0; 載入後再開啟。

    七、實戰監控指標

    八、總結:參數調優清單

    [mysqld]
    # Redo Log 檔案組:建議 4 個 x 1GB = 4GB,支撐高寫入
    innodb_log_files_in_group = 4
    innodb_log_file_size = 1G
    
    # 提交刷盤策略:核心業務用 1,非核心可用 2
    innodb_flush_log_at_trx_commit = 1
    
    # 髒頁比例上限:SSD 可調 70-80,HDD 保持 90
    innodb_max_dirty_pages_pct = 75
    
    # Log Buffer:大事務系統調大
    innodb_log_buffer_size = 64M
    
    # Page Cleaner 線程數:1.2+ 獨立線程,建議 4-8
    innodb_page_cleaners = 4
    
    # LRU 掃描深度:配合 page_cleaners
    innodb_lru_scan_depth = 2048
    

    延伸閱讀:Percona Blog、MySQL 官方手冊 InnoDB 章節、姜承尉《MySQL 內核:InnoDB 存儲引擎》。

    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved
    指標含義異常判斷
    Innodb_log_waits等待 Redo Log 空間計數>0 表示 Log 滿導致阻塞,需加大 log file size
    Innodb_buffer_pool_wait_free等待 Buffer Pool 空閒頁計數>0 表示髒頁刷盤跟不上
    Innodb_log_write_requests / Innodb_log_writes寫請求 vs 實際寫入比值過高說明 Buffer 過小或提交頻繁
    Innodb_os_log_fsyncsfsync 次數配合 flush_log_at_trx_commit 分析