InnoDB崩溃恢复依赖redo log和undo log实现自动前滚与回滚,结合doublewrite buffer防止撕裂页;MyISAM无日志机制,断电易致数据文件损坏,修复不可靠且需人工干预。

InnoDB崩溃恢复靠的是redo log和undo log,不是“猜”数据
InnoDB重启时能自动前滚已提交事务、回滚未提交事务,核心依赖两个日志文件:ib_logfile0(重做日志)和ibdata1中保存的undo日志。断电发生时,只要磁盘没物理损坏,这些日志里记录了“哪些页改过、改成什么样、改之前是什么样”。MySQL启动时扫描日志,按顺序重放+回滚,就能还原到崩溃前一致状态。
MyISAM没有这类日志——它写数据直接落盘到.MYD,写索引直接落盘到.MYI。断电可能只写完一半.MYD或.MYI,导致两者偏移错位。MySQL只能靠文件头标记(如crashed flag)和简单校验判断“疑似损坏”,但无法知道哪一行该回退、哪一页该丢弃,只能让用户自己决定怎么“修”。
双写缓冲区(doublewrite buffer)让InnoDB不怕“撕裂页”
当MySQL写一个16KB数据页时,如果断电发生在第8KB处,就会产生“撕裂页”(torn page)。InnoDB默认开启innodb_doublewrite=ON,它会先将这个页完整写入ibdata1里的连续2MB双写区,确认落盘成功后,再并发写入真实的.ibd文件。
- 崩溃后恢复时,InnoDB检查双写区里的页是否完整:完整就直接覆盖回
.ibd;不完整则跳过,用老版本页顶上 - MyISAM没有双写区,
.MYD里存的就是半截脏页,REPAIR TABLE只能靠.MYI反推.MYD偏移,一旦索引也损坏,就彻底没辙 - 禁用
innodb_doublewrite=OFF等于主动放弃页级防护,生产环境别碰
MyISAM的“repair”不是恢复,是重建+拼接,结果不可控
REPAIR TABLE t1或myisamchk --recover干的事,本质是:读.MYI重建索引结构,再按索引顺序从.MYD里“尽量捞数据”。这过程不保证原子性,也不校验逻辑一致性。
- 若
.MYI损坏但CHECK TABLE返回OK,查询结果可能静默错乱(比如漏行、主键重复) - 若
.MYD和.MYI都异常,修复大概率失败,甚至越修越糟 - 修复期间整张表锁死,大表可能卡住几十分钟——这不是“慢”,是服务中断
- InnoDB的
.ibd文件自带校验和,启动时自动检测并报错,不会静默返回错误数据
主从复制场景下,MyISAM崩溃会卡死SQL线程
InnoDB崩溃后从库重启,能正常拉起表并继续应用relay log,因为事务有明确的binlog position边界,可精准续传。MyISAM表一旦标记为crashed,复制线程一碰到它就停在Slave_SQL_Running: No,错误日志里反复报Table 'db.t1' is marked as crashed。
根本原因是MyISAM没有事务边界,复制线程无法跳过损坏表——它不像InnoDB那样能定位到某条语句的commit点。这种卡死往往需要人工介入STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;,但跳过的那条语句可能正是关键业务逻辑。
真正容易被忽略的是:MyISAM的“轻量”只体现在代码路径短,它的可靠性成本全堆在运维响应上——而InnoDB把这部分成本转嫁给了磁盘IO和内存开销,换来的是故障时无人值守的自动恢复能力。


















