萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

InnoDB 崩潰無法啟動?innodb_force_recovery 緊急搶救實戰

事故現場

創業公司主機磁碟陣列損壞導致宕機,重啟 MySQL(MariaDB 5.5.37)報錯:

InnoDB: Doing recovery: scanned up to log sequence number 9120034833
[ERROR] mysqld got signal 11

日誌檔損壞,InnoDB 嘗試 Redo Log 恢復時觸發 Segfault,服務無法啟動。

核心參數:innodb_force_recovery

跳過損壞頁面檢查、背景線程、事務回滾、Change Buffer 合併、Undo Log 掃描、Redo Log 前滾等恢復步驟,強行拉起實例以 唯讀模式 導出資料。

級別常數行為
1SRV_FORCE_IGNORE_CORRUPT忽略檢測到的損壞頁
2SRV_FORCE_NO_BACKGROUND阻止 Master Thread(含 Full Purge)運行
3SRV_FORCE_NO_TRX_UNDO不執行事務回滾
4SRV_FORCE_NO_IBUF_MERGE不合併 Insert Buffer
5SRV_FORCE_NO_UNDO_LOG_SCAN不看 Undo Log,視未提交事務為已提交
6SRV_FORCE_NO_LOG_REDO不執行 Redo Log 前滾

級別遞增包含前級別行為。≥1 時僅支援 SELECT/CREATE/DROP,禁止 DML。

關鍵坑點:innodb_purge_threads 與 force_recovery 共用導致無限等待

my.cnf 同時設定:

innodb_force_recovery = 6
innodb_purge_threads = 1  # 預設值

會陷入死循環:

InnoDB: Waiting for the background threads to start ... (無限重複)

根因:源碼中 srv_master_thread 啟動邏輯要求 Purge Thread 就緒,但 force_recovery>1 禁止 Purge Thread,雙方互等。

解法:innodb_purge_threads = 0 禁用 Purge Thread,配合 force_recovery=6 即可順利啟動。

完整搶救流程

  1. 修改 my.cnf:
    innodb_force_recovery=6
    innodb_purge_threads=0
  2. 啟動 MySQL,確認進入 ready for connections 狀態。
  3. 立即邏輯導出全庫:mysqldump --all-databases > all.sql。
  4. 關庫,將參數歸零(force_recovery=0, purge_threads=1)。
  5. 重建實例、匯入資料、驗證業務。

版本差異提示

MySQL 5.5 及之前:innodb_purge_threads=1 固定,force_recovery>1 必須設 purge_threads=0。
5.6+ 多 Purge Thread 架構改善,但保守策略仍建議搶救時關閉 Purge。

事後複盤

  • 磁碟故障屬硬體層面,RAID 卡快取策略、BBU 電池健康度需納入巡檢。
  • MySQL 5.6+ 開啟 sync_binlog=1 + innodb_flush_log_at_trx_commit=1 + relay_log_recovery=ON(Crash-Safe Replication)可最大程度規避 1594/1236 錯誤。
  • 備份驗證機制(定期恢復演練)是最後防線。
copyright © 萬盛學電腦網 all rights reserved