必须停掉mysqld服务,否则myisamchk修复极大概率导致数据丢失或二次损坏,因其直接读写.myd/.myi文件,而mysqld运行时也在并发修改这些文件,即使禁用外部锁定也无法保证操作同步,易引发行缺失、重复或文件结构破坏。

必须先停掉 mysqld 服务,否则 myisamchk 修复极大概率导致数据丢失或二次损坏。
为什么不能边运行 mysqld 边用 myisamchk 修复
MyISAM 表由 .MYD(数据)和 .MYI(索引)两个物理文件组成,myisamchk 会直接读写这些文件。而 mysqld 在运行时也持续读写它们——哪怕启用了 --skip-external-locking,也无法保证 myisamchk 和 mysqld 的操作完全同步。
常见后果包括:
- 修复后表能打开,但部分行缺失或重复
-
myisamchk报 “table is crashed”,而实际只是被 mysqld 锁住,误判为损坏 - 修复中途 mysqld 写入新数据,
.MYD文件结构被破坏
唯一安全做法:执行 mysqladmin shutdown 或 systemctl stop mysql,确认 mysqld 进程已退出,再运行 myisamchk。
怎么判断该用 --recover 还是 --safe-recover
两者都用于修复损坏的 MyISAM 表,但策略不同:
-
--recover(简写-r):尝试重建索引,速度快,适用于大多数索引损坏(如错误 126、145)。它会丢弃无法定位的行,但保留主键/唯一键约束 -
--safe-recover(简写-o):逐行扫描.MYD文件重建整个表,兼容性更强,能处理更严重的损坏(如错误 127、134),但耗时长、内存占用高,且可能恢复出“垃圾行”
实操建议:
- 先试
myisamchk -r tbl_name.MYI;如果报错 “Can't create new tempfile” 或 “Record file is crashed”,说明数据文件损坏严重,必须换--safe-recover - 若表有大量删除/更新历史,优先用
--safe-recover,避免因索引偏移导致行错位
修复前必须做的三件事
别跳过,否则修完发现数据没了就晚了:
- 用
cp tbl_name.MYD tbl_name.MYI /backup/path/备份原始文件——myisamchk不自动备份,--backup只备份.MYD,不保.MYI - 确认表路径:如果不在数据库目录下运行
myisamchk,必须指定完整路径,例如myisamchk -r /var/lib/mysql/dbname/tbl_name.MYI - 查清错误码:看到报错里有类似
error 135这样的数字,立刻运行perror 135,它不是普通损坏,而是.MYD文件空间耗尽,需用ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy调整参数,myisamchk无法解决
修复后验证是否真好了
运行 myisamchk -c tbl_name.MYI 只是检查文件头是否可读,不代表数据逻辑正确。真正有效的验证方式只有两种:
- 启动 mysqld 后,执行
SELECT COUNT(*) FROM tbl_name和SELECT * FROM tbl_name ORDER BY primary_key LIMIT 10—— 观察是否返回预期结果,有没有乱码、NULL 值异常增多 - 用
myisamchk -e tbl_name.MYI(--extend-check)做深度校验,但它会显著变慢,且可能把正常删除的空洞识别为损坏
最常被忽略的一点:myisamchk 修复完不会自动更新表的“crash flag”。即使修复成功,下次 mysqld 启动仍可能因残留标记再次触发自动检查。务必在修复后手动删掉 .MYI 文件里的崩溃标记,或直接用 REPAIR TABLE tbl_name(在 mysqld 启动后)覆盖一次,才能彻底清除状态。











