repair table仅适用于myisam表,innodb执行会报error 1031;需先用show create table确认引擎,再据check table结果选quick(仅修索引)、extended(逐行重建)或use_frm(极端情况),修复后必须执行analyze table并用explain验证。

看到Incorrect key file for table就该动手,但先确认是不是MyISAM
REPAIR TABLE只对MyISAM有效,InnoDB表执行会直接报错ERROR 1031 (HY000): Table storage engine for 'xxx' doesn't support repair。别被“crashed”字样误导——MySQL日志里写Table 'xxx' is marked as crashed,不等于数据坏了,很可能是MyISAM的.MYI索引文件挂了。查引擎最稳的方式是:SHOW CREATE TABLE xxx,输出里必须有ENGINE=MyISAM;或者跑SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'xxx'。系统库如mysql.user在5.7及以前是MyISAM,8.0+已转InnoDB,旧经验不能套用。
CHECK TABLE结果决定REPAIR TABLE用哪个参数
CHECK TABLE xxx不是摆设,它返回的Msg_text直接告诉你该怎么修:
- 返回
status = OK:不用修,可能是临时状态异常或缓存问题 - 提示
record delete-link chain broken:数据链断裂,必须用REPAIR TABLE xxx EXTENDED - 报
key file is corrupted但没提数据问题:先试REPAIR TABLE xxx(等价于QUICK模式) - 连
.MYI都读不出来(比如Can't read keyfile):只能上REPAIR TABLE xxx USE_FRM,但修复后索引指向可能错位
REPAIR TABLE xxx QUICK只重建索引树,不碰.MYD数据文件,快但对真实损坏基本无效;EXTENDED会逐行扫描.MYD重建整个索引,能修逻辑错位,但要求tmpdir至少有原.MYI大小的2倍空闲空间;USE_FRM丢弃所有现有索引结构,纯靠.FRM重建,期间表不可读写,且无法保证全文索引或前缀索引语义正确。
修复前必须检查三件事,缺一不可
MyISAM修复不可逆,失败可能让表彻底不可读:
- 备份原始三件套:
cp /var/lib/mysql/dbname/xxx.{MYD,MYI,FRM} /backup/,哪怕只是临时拷贝也比没强 - 确认磁盘空间:
SELECT @@tmpdir,确保该路径剩余空间 ≥ 原.MYI大小的2倍(EXTENDED模式会生成xxx.TMD临时文件) - 检查权限:
mysql用户必须对tmpdir和数据库目录有读写权限,否则报Errcode: 13 (permission denied)
特别注意:.FRM是二进制文件,被vim/cat修改过、或跨MySQL版本拷贝(比如5.7的.FRM放到8.0实例),会导致ERROR 1033 (HY000): Incorrect information in file,这时REPAIR TABLE根本不会启动。
修复后不验证 = 白修
REPAIR TABLE返回OK只代表命令执行成功,不代表索引真能用。MyISAM的.MYI不存校验和,修复后可能指向错误的.MYD行号,这种错位MySQL自己发现不了:
- 立刻执行
ANALYZE TABLE xxx:否则优化器仍按旧统计信息估算,EXPLAIN里key列为空、rows值巨大,都是因为它还在用坏掉的旧分布 - 用
EXPLAIN SELECT验证关键查询:确认key列显示预期索引名,且rows明显下降(比如从100万降到几百) - 查重复值:
SELECT key_col, COUNT(*) FROM xxx GROUP BY key_col HAVING COUNT(*) > 1;USE_FRM模式下若数据本就有重复,修复过程可能跳过冲突行,导致业务逻辑出错
最容易被忽略的是“修复成功但查询变慢数倍”的静默失效——索引结构看似恢复,但指向错乱,只能靠EXPLAIN和抽样查询暴露。











