必须先确认引擎为myisam才能执行repair table,innodb表执行会报错或无效;通过show create table或show table status查看engine字段,避免误操作干扰崩溃恢复流程。

确认是不是 MyISAM 表才适用 REPAIR TABLE
看到 Table 'xxx' is marked as crashed and should be repaired,第一反应别急着修,先查引擎:SHOW CREATE TABLE xxx;。如果返回里是 ENGINE=MyISAM,才能走修复流程;如果是 ENGINE=InnoDB,REPAIR TABLE 直接报错或无效,硬试可能干扰崩溃恢复流程。
常见误操作:在 InnoDB 表上反复执行 REPAIR TABLE,不仅没用,还可能掩盖真实错误(比如 InnoDB: Database page corruption 被日志刷过去)。
- 查表状态更直观:
SHOW TABLE STATUS LIKE 'xxx';,看Engine列和Comment列是否含crashed - MyISAM 表对应磁盘文件是
xxx.MYD+xxx.MYI;InnoDB 依赖ibdata1或独立.ibd文件 - 错误日志里搜
crashed基本锁定 MyISAM;搜corruption、page、innodb_force_recovery多指向 InnoDB
在线修复优先用 CHECK TABLE + REPAIR TABLE,但注意锁和并发
REPAIR TABLE xxx; 是最轻量的在线修复方式,但它要求表当前没被其他线程写入——否则会卡住,甚至触发 Lock wait timeout。实操前务必先 CHECK TABLE xxx;,返回 Status: OK 就不用动;只有 Status: error 或 warning 才需要下一步。
别跳过这步直接修。有些表只是临时标记(比如 mysqld 异常退出后未清理标志位),CHECK TABLE 能自动清除假阳性。
- 修复时加
USE_FRM参数可强制重建索引:REPAIR TABLE xxx USE_FRM;,适用于.MYI严重损坏但.frm和.MYD完好时 - 若报
Can't repair table, need rebuild,说明索引结构已不可逆损坏,必须切到离线工具 - 高并发场景下,
REPAIR TABLE会阻塞所有对该表的 DML,评估业务影响再操作
离线修复必须停服务或锁库,用 myisamchk 且路径要对
当 REPAIR TABLE 失败,或你确定 mysqld 正在写入该表(无法保证空闲),就得停 MySQL 服务,改用 myisamchk。关键点:路径不能错,.MYI 文件位置得从 datadir 和数据库名拼出来,比如 /var/lib/mysql/mydb/xxx.MYI。
别在运行中的 mysqld 上直接跑 myisamchk ——即使加了 --skip-locking,也极大概率导致二次损坏。官方明确说:“If you run myisamchk to check tables that mysqld is updating at the same time, you may get a warning that a table is corrupt even when it is not.”
- 快速检查:
myisamchk -s /var/lib/mysql/mydb/xxx.MYI(-s是 silent 模式) - 标准修复:
myisamchk -r /var/lib/mysql/mydb/xxx.MYI - 顽固损坏用安全模式:
myisamchk --safe-recover /var/lib/mysql/mydb/xxx.MYI(慢但能处理索引全丢的情况) - 批量修复整个库:
myisamchk -r /var/lib/mysql/mydb/*.MYI
InnoDB 表出现类似症状时,REPAIR TABLE 是无效动作
如果你在 InnoDB 表上看到 marked as crashed 报错,基本是误判或日志混淆。InnoDB 不会“标记为 crashed”,它要么启动失败(日志里满屏 InnoDB: Database page corruption),要么查询时断连(ERROR 2013)。这时候强行 REPAIR TABLE 不仅无响应,还可能让 ibdata1 状态更混乱。
真正该做的是:立刻查错误日志,逐级尝试 innodb_force_recovery(1–6),启动后尽快 mysqldump 导出数据,然后重建实例。别指望“修好就继续用”——InnoDB 的页损坏通常是底层存储问题的表征,不换磁盘/排查 I/O,修完还会崩。
-
innodb_force_recovery = 1:跳过回滚段,能读不能写 - 导出时加
--single-transaction避免锁表,但 recovery >3 时该参数会失效 - 导出后务必校验行数、主键连续性、关键时间字段(比如订单创建时间是否突变),防止部分页静默损坏











