MySQL 表损坏修复:MyISAM 和 InnoDB 是两套完全不同的打法

来源:互联网 时间:2026-09-08

网站某栏目突然打不开,日志里刷 Table is marked as crashed,或者 MySQL 莫名重启后某张表查一下就断连——表损坏来了。动手修之前必须先搞清楚一件事:出问题的是 MyISAM 表还是 InnoDB 表,两者修法完全不同,用错方法轻则无效,重则把还能救的数据弄没。SHOW TABLE STATUS 看一眼 Engine 列,第一步就定方向。

先讲清楚“表为什么会坏”:写入写到一半断电或被强杀、磁盘坏道、硬件故障、外部程序同时改表,都是常见诱因。损坏是结果,修表只是止损,查诱因才是根治——这个后面收尾再展开。

MyISAM 的修复相对简单,官方给了 REPAIR TABLE 语句,ARCHIVE 和 CSV 表同样适用。修复前做一件事:停库备份 /var/lib/mysql 数据目录,修复操作本身也有失败概率,先给自己留退路。REPAIR 的输出里 Msg_type 是 status、Msg_text 是 OK 就算修好了;不行就走 mysqlcheck 命令行,或者 myisamchk 离线修。

-- 动手前先备份(MyISAM):
-- systemctl stop mysqld && cp -r /var/lib/mysql /var/lib/mysql_bkp
-- systemctl start mysqld

-- 在线检查与修复
CHECK TABLE t1;
REPAIR TABLE t1;

-- 全库扫描修复(mysqlcheck,比逐表执行 REPAIR 省事)
-- mysqlcheck --repair --databases db_name
-- mysqlcheck --repair --all-databases

InnoDB 完全不同:它没有 REPAIR TABLE 可用。InnoDB 靠页校验和机制自动检测损坏,读到坏页会主动停库,常规问题靠重启后的崩溃恢复自愈。真遇上页损坏,官方给的路径是“导出再导入”:用 mysqldump 把表数据逻辑导出,删表重建再灌回去。如果损坏严重到 InnoDB 起不来,才轮到 innodb_force_recovery 登场。

# my.cnf 的 [mysqld] 段加(从 1 开始,逐步试,能导出数据即停)
# innodb_force_recovery = 1

# 起库后立刻导出(1-3 档相对安全)
mysqldump db_name t1 > t1_out.sql

# 官方红线:4 档及以上可能永久损坏数据文件
# 1 跳过坏页 / 2 禁后台线程 / 3 禁回滚
# 4 禁插入缓冲合并 / 5 禁undo扫描 / 6 禁redo前滚(最危险)

force_recovery 的使用纪律必须背下来:永远从 1 开始,能以低档位导出数据就绝不开高档;4 以上任何一档都可能造成不可逆的永久损坏,官方原文写得明明白白,只允许你在单独的物理副本上验证过才考虑在生产用。导出后 Drop 表、去掉 force_recovery 参数正常重启、再导入数据,这才算完整闭环。另外记住一个坑:force_recovery 模式下 InnoDB 是只读的,OPTIMIZE TABLE 之类的重建操作会直接报错,别在那里面较劲。

修完之后是防复发:查 dmesg 和 MySQL 错误日志里的硬件层报错,坏道和 RAID 卡故障是表损坏最常见的幕后真凶,只修表不修盘,过阵子还得再来一次。同时把备份策略落实——每天全备加 binlog,损坏场景下才有“回滚到任意时点”的底气。表损坏是结果不是原因,硬件健康检查和备份体系才是治本。

相关阅读:表损坏属于数据层的修复类故障。《服务器故障排查总纲:按现象反查的五层定位法》把本篇和备份、白屏排在相邻位——修不好的时候,恢复靠的就是前面建好的备份体系。

相关文章

标签:

A5创业网 版权所有