MyISAM无WAL机制,崩溃易丢数据且文件易损坏;InnoDB通过redo log+行级锁+页校验保障原子性、一致性与可恢复性,是高写入场景的必需选择。

MyISAM没有WAL机制,写入中途崩溃就直接丢数据
MyISAM采用“直接写盘”模式:INSERT/UPDATE时,先改内存缓存,再异步刷到.MYD和.MYI文件。一旦在刷盘过程中断电、kill -9 mysqld 或磁盘IO卡住,.MYD 文件里就会留下半截记录、断裂的链表指针或校验不一致的块——这正是 record delete-link chain broken 的根源。InnoDB则靠 redo log 保证原子性:哪怕写到一半挂了,重启后也能按日志重放,不会出现中间态损坏。
表级锁导致写操作排队,长时间持有文件句柄增加损坏风险
MyISAM所有写操作都得获取整张表的写锁,高并发下大量线程阻塞在 Waiting for table level lock 状态。这意味着一个慢写(比如大事务或磁盘延迟)会让其他写请求持续占用文件句柄、延长.MYD/.MYI被锁定的时间。若此时发生异常中断,多个未完成的写上下文叠加,更容易破坏文件结构一致性。而InnoDB的行级锁把影响范围收敛到单行,降低文件层面的冲突概率。
无校验、无事务,坏块无法检测也无法跳过
- MyISAM不为数据块做CRC或checksum,读到翻转字节或扇区错误时不会报错,而是静默返回脏数据或直接中断
- 遇到物理损坏,MySQL底层IO层会直接失败,
REPAIR TABLE又依赖完整读出.MYD才能重建,形成死循环 - InnoDB每个页自带checksum,读取时校验失败直接报
Corrupted page并可触发自动恢复流程
修复过程本身可能加剧损坏
很多人在MySQL运行时执行 REPAIR TABLE table_name EXTENDED,但这个命令会生成临时文件 table_name.TMD 并尝试全量重写.MYD。一旦磁盘空间不足(需 ≥ Data_length 的2倍)、.MYD 属主不是 mysql 用户,或IO再次出错,它就会静默失败甚至把原表置为 ERROR 1033 状态。真正能抢救的只有停服后用 myisamchk --safe-recover,但它只能跳过坏块提取可读行,丢失的数据再也找不回来。
最常被忽略的一点是:MyISAM损坏往往不是单点故障,而是系统性风险暴露——比如磁盘开始掉坏道、UPS失效、或长期未 OPTIMIZE TABLE 导致碎片堆积。修复完一张表,不代表其他MyISAM表安全。真要扛频繁写入,换InnoDB不是优化选项,是止损底线。


















