myisam表异常宕机后极易损坏,根本原因是无事务日志、无原子性保障且.myd与.myi物理分离;宕机时文件写入中断导致数据或索引残缺,表现为“table is marked as crashed”等错误,修复需据损坏程度选用repair table quick/extended/use_frm,并严格遵循备份、验引擎、保磁盘空间三前提。

MyISAM表在MySQL异常宕机后极易损坏,根本原因在于它没有事务日志、不保证写操作原子性,且数据文件与索引文件物理分离——宕机时任意一个文件写到一半就可能残缺。
MyISAM没redo/undo日志,崩溃后无法重放或回滚
InnoDB靠redo log重放未刷盘的事务、靠undo log回滚未提交的修改,重启自动完成崩溃恢复;MyISAM完全没这两样东西。一旦mysqld被kill -9、断电或OOM杀死,正在写的.MYD(数据)或.MYI(索引)文件就停在中间状态:可能某一行只写了一半,某个B+树节点只更新了部分指针。
常见表现:
- 查询报
Table 'xxx' is marked as crashed或Incorrect key file for table -
SHOW TABLE STATUS里Comment列显示crashed - 用
myisamchk -s检查直接提示key block not sorted或data record length mismatch
.MYD和.MYI是两个独立文件,损坏常不对称
MyISAM把数据存.MYD、索引存.MYI,写入时两者不同步。比如磁盘满时,.MYI可能因空间不足写失败,而.MYD已落盘——这时CHECK TABLE可能返回OK,但查询会漏行或返回错误结果,属于“静默损坏”。
修复时也受限:
-
REPAIR TABLE ... QUICK只修.MYI,前提是.MYD完好;若.MYD也坏,就会报Failed repairing the table -
REPAIR TABLE ... USE_FRM能重建空索引,但所有索引失效,后续必须ANALYZE TABLE或手动CREATE INDEX - 没有
innodb_force_recovery这类兜底机制,要么修好,要么丢数据
表级锁放大宕机风险,修复过程本身又成单点故障
MyISAM所有写操作都锁整张表,大表上一个慢UPDATE卡住几秒,后面一堆请求排队;此时若恰好宕机,损坏概率指数上升。更麻烦的是修复本身:
-
REPAIR TABLE全程锁表,千万级表修复可能持续几十分钟,业务完全不可写 - 修复需临时空间≥表大小2倍,磁盘稍紧就中断,还可能留下残留损坏碎片
- 修复失败后只能切到
myisamchk --safe-recover,但这要求停库,生产环境很难协调
真正难处理的不是“修不好”,而是“修完才发现数据逻辑已错乱”——比如索引损坏导致WHERE id = 123查不到本该存在的行,应用层无感知,直到下游出账错误。这种问题不会报错,只会悄悄漏数据。











