MyISAM 表在斷電、殺進程、磁碟故障後易發生 Table '...' is marked as crashed and should be repaired。本文詳解 myisamchk 三級修復模式、資料檔重建索引、.frm 損壞重建、以及遷移 InnoDB 徹底根治方案。
kill -9 → 緩衝區未刷盤,.MYI 損壞。# 停止 MySQL 服務 (必須離線操作)
systemctl stop mysql
# 1. 快速修復 (僅修復索引樹,最快)
myisamchk --recover --quick /var/lib/mysql/db_name/table_name.MYI
# 2. 標準修復 (重建索引,修復資料列刪除標記)
myisamchk --recover /var/lib/mysql/db_name/table_name.MYI
# 3. 安全修復 (逐行讀取資料檔重建索引,最慢但最徹底)
myisamchk --safe-recover /var/lib/mysql/db_name/table_name.MYI
# 修復後檢查
myisamchk --check /var/lib/mysql/db_name/table_name.MYI
# 重啟服務
systemctl start mysql
# 1. 備份資料檔
cp /var/lib/mysql/db_name/table_name.MYD /tmp/
# 2. 進入 MySQL 刪除表內容 (保留結構)
mysql -e "DELETE FROM db_name.table_name;"
# 3. 退出 MySQL,用備份覆蓋空資料檔
cp /tmp/table_name.MYD /var/lib/mysql/db_name/table_name.MYD
# 4. 標準修復 (根據 .MYD + .frm 重建 .MYI)
myisamchk --recover /var/lib/mysql/db_name/table_name.MYI
# 1. 備份 .MYD .MYI
cp /var/lib/mysql/db_name/table_name.{MYD,MYI} /tmp/
# 2. 刪除舊表檔案 (含 .frm)
rm /var/lib/mysql/db_name/table_name.*
# 3. 用原建表 SQL 重建 (需保存原 DDL)
mysql -e "CREATE TABLE db_name.table_name (...) ENGINE=MyISAM;"
# 4. 覆蓋資料/索引檔
cp /tmp/table_name.{MYD,MYI} /var/lib/mysql/db_name/
# 5. 標準修復
myisamchk --recover /var/lib/mysql/db_name/table_name.MYI
| 參數 | 說明 |
|---|---|
-c, --check | 僅檢查不修復 |
-r, --recover | 標準修復 |
-q, --quick | 快速模式 (配合 -r) |
-o, --safe-recover | 安全模式 |
-f, --force | 覆蓋舊 .TMD 暫存檔 |
--parallel-recover | 並行修復 (多核) |
--sort_buffer_size=256M | 排序緩衝 (大表加速) |
--key_buffer_size=512M | 索引緩衝 |
-- MySQL 內建 (需 MyISAM 表)
REPAIR TABLE db_name.table_name; -- 相當於 --recover
REPAIR TABLE db_name.table_name QUICK; -- 相當於 --recover --quick
REPAIR TABLE db_name.table_name EXTENDED; -- 相當於 --safe-recover
-- 但 REPAIR TABLE 仍會鎖表,大表業務不可用
ALTER TABLE db_name.table_name ENGINE=InnoDB;
-- 獲得:事務、行鎖、Crash-safe、Foreign Key、線上 DDL (8.0+)
-- 代價:磁碟空間 +20~30%、主鍵查詢略慢 (聚簇索引雙層查找)
若業務無全文搜尋/空間索引需求,**強制遷移 InnoDB** 是一次性解決 MyISAM 損壞、鎖表、無事務等所有歷史包袱的最佳選擇。
結語:myisamchk 是搶險工具,不是常態手段。建立「MyISAM 零容忍」政策:新表預設 InnoDB、存量表計劃遷移、備份驗證包含 CHECK TABLE,才能從根本上消除索引損壞風險。