没有备份时修复mysql索引损坏崩溃,本质是抢救数据:innodb用innodb_force_recovery=1~4逐级启动导出,myisam严重损坏则停服后myisamchk离线修复;严禁对innodb执行repair table或依赖optimize table修复。

没有备份时修复 MySQL 索引损坏引起的崩溃,本质是“抢救数据而非修复索引”——InnoDB 没有真正可执行的在线修复命令,MyISAM 的 REPAIR TABLE 在严重损坏时也常失败。此时必须切换思路:先让 MySQL 启动起来,导出还能读的数据,再重建。
确认引擎类型和损坏程度,别对 InnoDB 执行 REPAIR TABLE
执行 CHECK TABLE tbl_name 前,先查清引擎:SHOW TABLE STATUS LIKE 'tbl_name'。如果 Engine 是 InnoDB,跳过所有 REPAIR TABLE 尝试——它会直接报错 The storage engine for the table doesn't support repair,浪费时间还可能干扰恢复流程。MyISAM 表若返回 status = corrupt 或报错 Incorrect key file for table,才进入修复路径。
InnoDB 崩溃无法启动:用 innodb_force_recovery 逐级抢数据
MySQL 进程起不来(日志里出现 MY-012562、MY-013183 或 Database page corruption),说明已存在物理页损坏。这时唯一可行路径是强制启动并导出:
- 停止 mysqld(
systemctl stop mysqld) - 编辑
/etc/my.cnf,在[mysqld]下添加innodb_force_recovery = 1,注释掉其他级别 - 启动服务:
systemctl start mysqld;若失败,改=2再试,最高到=4(=4会禁写入,仅用于导出) - 启动成功后立刻执行:
mysqldump -u root -p --single-transaction db_name tbl_name > tbl_recover.sql - 导出完成马上停服务,不要做任何写操作
注意:innodb_force_recovery = 5 或 =6 可能导致数据不一致,且导出结果不可信,不建议越过 =4。
MyISAM 表卡在 Repair with keycache failed?切到 myisamchk 离线修复
当 REPAIR TABLE tbl_name 报错 Repair with keycache failed 或反复提示 Key block size is wrong,说明 .MYI 文件已有字节级损坏,SQL 层修复无能为力:
- 必须先停掉 mysqld(
systemctl stop mysqld) - 找到真实数据路径:
SELECT @@datadir;,然后定位到db_name/tbl_name.MYI - 运行:
myisamchk --safe-recover --force /var/lib/mysql/db_name/tbl_name.MYI - 若仍失败,尝试更激进的
myisamchk -r -v /path/to/tbl_name.MYI(-r表示 recover,-v显示过程) - 修复后启动 mysqld,立刻执行
ANALYZE TABLE tbl_name更新统计信息
myisamchk 不依赖 MySQL 进程,但要求磁盘剩余空间 ≥ 原 .MYI 文件大小,否则会静默失败。
导出后重建表,别信 OPTIMIZE TABLE 能“修好”
无论 MyISAM 还是 InnoDB,只要经历过崩溃或强制恢复,都不要用 OPTIMIZE TABLE 当修复手段:
- 对 MyISAM,它等价于
REPAIR + ANALYZE,但前提是索引文件未断裂;已损坏时执行会卡在Opening tables或报Can't repair table - 对 InnoDB,它本质是
ALTER TABLE ... FORCE,需全表扫描读取 ibd;若页损坏,进程大概率直接 crash - 正确做法是:导出后
DROP TABLE,再mysql -u root -p db_name
最易被忽略的一点:即使导出成功、导入无报错,也必须验证关键查询是否走对索引——用 EXPLAIN 看 key 列是否命中预期索引,rows 是否合理。损坏后的重建表,统计信息可能滞后,优化器容易误判。











