
MyISAM表索引损坏时,REPAIR TABLE 是最直接的修复手段
MyISAM 不支持事务和崩溃安全写入,意外断电、强制 kill mysqld 或磁盘满都可能导致 .MYI(索引文件)损坏,表现为查询报错 Incorrect key file for table 'xxx'; try to repair it。这时别急着重建表或导出导入,REPAIR TABLE 就是专为这种场景设计的原生命令。
- 必须在 MySQL 服务运行状态下执行,且用户需有
ALTER和CREATE权限 - 推荐先用
CHECK TABLE xxx确认损坏类型:若返回status = OK就不用修;若返回error或warning,再执行修复 - 默认使用
QUICK模式(只修复索引树结构),速度最快但不校验数据行;如果CHECK TABLE提示 “record delete-link chain broken”,就得加EXTENDED参数:REPAIR TABLE xxx EXTENDED - 严重损坏(如索引文件完全无法读取)可能触发
USE_FRM模式——它会丢弃现有.MYI,仅靠.FRM结构重新生成空索引,再逐行扫描.MYD重建,耗时长且期间表锁死
修复失败常见原因和绕过方法
不是所有损坏都能靠 REPAIR TABLE 拯救。遇到 Repair with keycache failed 或反复提示 Key block size is wrong,基本说明索引文件已部分字节错乱,MySQL 解析器卡住了。
- 确认磁盘空间充足:修复过程会临时生成新
.MYI,至少需要和原索引文件等大的空闲空间 - 检查
my.cnf中myisam_recover_options是否被设为FORCE或BACKUP,这会影响自动修复行为,手动执行时建议显式指定模式 - 若
REPAIR TABLE失败且无备份,可尝试用myisamchk命令行工具离线修复:myisamchk --safe-recover --force /var/lib/mysql/dbname/table.MYI(注意先停掉 mysqld 或锁表) -
myisamchk -r(recover)比-o(optimize)更激进,会重排索引块,适合结构错位;但若数据本身已损坏,它可能把错误固化到新索引里
修复后必须验证索引是否真正可用
命令返回 OK 不代表索引能正常工作——尤其当表有全文索引(FULLTEXT)或前缀索引时,REPAIR TABLE 可能跳过某些校验。
- 立刻执行
ANALYZE TABLE xxx更新统计信息,否则优化器可能继续走错执行计划 - 对关键查询做
EXPLAIN,确认key列显示预期索引名,rows值合理(非全表扫描) - 如果表有
UNIQUE索引,务必查一遍是否有重复值被悄悄忽略:SELECT key_col, COUNT(*) FROM xxx GROUP BY key_col HAVING COUNT(*) > 1 - MyISAM 的
.MYI不存数据校验和,修复后无法自动发现索引指向了错误的.MYD行号,这种错位只能靠业务逻辑层校验暴露
长期避免索引损坏的关键动作
依赖定期 REPAIR TABLE 是被动防守。MyISAM 的脆弱性根源在于其文件级锁和无日志机制,所以预防比修复更重要。
- 禁用
skip-external-locking(默认已禁用),确保外部工具(如myisamchk)不会与 mysqld 冲突操作同一文件 - 写密集场景下,把
delay_key_write设为ON能减少索引写入频率,但服务器异常宕机时会增加损坏概率,权衡后建议只对只读或低频更新表开启 - 监控
SHOW GLOBAL STATUS LIKE 'myisam%'中的Myisam_waits_for_key_cache和Myisam_key_reads,持续升高说明索引缓存不足,可能加剧磁盘 I/O 压力导致写入中断 - 真正的底线是:只要业务允许,优先迁移到 InnoDB。MyISAM 的修复能力再强,也补不上没有崩溃恢复、没有行锁、没有 MVCC 这些本质缺口










