最直接有效的修复方式是用repair table,但必须先确认表为myisam、通过check table判断损坏程度(如record delete-link chain broken需extended模式),并完成备份、磁盘空间检查和权限确认三前提;innodb表不支持该命令。

MyISAM表因非正常关闭(如断电、kill -9 mysqld、磁盘满)导致索引损坏,最直接有效的修复方式是用REPAIR TABLE,但必须配合CHECK TABLE判断损坏程度,并严格满足前提条件——否则可能让表彻底不可读。
先确认是不是 MyISAM 表且真坏了
别跳步。InnoDB 表执行REPAIR TABLE会报错Storage engine for the table doesn't support repair,纯属浪费时间。
- 查引擎:
SHOW CREATE TABLE table_name;确认含ENGINE=MyISAM - 看错误日志:
SELECT @@log_error;后用grep -i crashed /var/lib/mysql/xxx.err找线索 - 运行
CHECK TABLE table_name;:- 返回
status = OK→ 不用修 - 返回
Msg_text含record delete-link chain broken或data record is corrupted→ 必须修,且得用EXTENDED - 报
Incorrect key file for table→ 典型 .MYI 损坏,QUICK可能够用
- 返回
REPAIR TABLE 三种模式怎么选才不翻车
REPAIR TABLE 不是万能按钮,模式选错要么修不掉问题,要么把表锁死几小时还失败。
-
REPAIR TABLE table_name;(等价于QUICK):只重建 .MYI 索引树,不碰 .MYD 数据文件。快,但仅适用于索引节点断裂、数据行完好场景。CHECK 返回 OK 但查询乱序时可试 -
REPAIR TABLE table_name EXTENDED;:逐行扫描 .MYD,重建整个 .MYD + .MYI。能修record delete-link chain broken类逻辑错乱,但要求磁盘空闲空间 ≥ 表数据大小的 2 倍,期间全表锁死 -
REPAIR TABLE table_name USE_FRM;:丢弃原 .MYI,仅按 .FRM 文件结构重建空索引,再全扫 .MYD 补数据。仅当 .MYI 完全无法解析时用——风险高,UNIQUE 约束失效、全文索引语义丢失都可能发生
修复前必须做这三件事,缺一不可
MyISAM 修复无回滚,出错即不可逆。很多“修完更慢”“查出重复值”的问题,都源于跳过这几步。
- 备份原始三件套:
cp /var/lib/mysql/dbname/table_name.{MYD,MYI,FRM} /backup/。哪怕只是临时 cp,也比没强 - 确认磁盘空间:查
SELECT @@tmpdir;,确保该路径剩余空间 ≥ 原 .MYI 大小的 2 倍(EXTENDED模式会生成table_name.TMD临时文件) - 检查权限:MySQL 进程用户(如
mysql)必须对tmpdir有读写权限,否则报Errcode: 13 (permission denied)
修复后验证比修复本身更重要
命令返回 OK 只代表语法执行成功,不代表索引能真正工作。MyISAM 的 .MYI 不存数据校验和,修复后可能指向错误的 .MYD 行号,这种错位不会报错,只会让查询变慢数倍或返回错数据。
- 立刻执行
ANALYZE TABLE table_name;,否则优化器仍用旧统计信息,EXPLAIN 很可能显示key = NULL - 对关键查询跑
EXPLAIN SELECT ...,确认key列显示预期索引名,rows值明显下降(比如从百万级降到几百) - 若有 UNIQUE 索引,必须查重复:
SELECT key_col, COUNT(*) FROM table_name GROUP BY key_col HAVING COUNT(*) > 1。REPAIR 使用USE_FRM时极易悄悄忽略冲突行











