mysql崩溃后自动恢复需redo log和undo log完好,启动时通过错误日志中“database was not shutdown normally!”等行判断是否触发恢复;重做阶段重放已提交事务的物理修改,回滚阶段用undo log前镜像反向修正内存页;双重写机制在redo前修复损坏页,确保重放安全。

MySQL崩溃后能自动恢复数据,前提是redo log和undo log文件没损坏——它不是“猜”或“修复”,而是严格按日志重放和回滚,保证已提交事务不丢、未提交事务不生效。
怎么判断MySQL启动时是否进入崩溃恢复?
看错误日志(如/var/lib/mysql/hostname.err)里有没有这两类关键行:
-
Database was not shutdown normally!或Database system was interrupted; will perform recovery—— 这是明确信号,表示已触发恢复流程 -
Starting crash recovery from checkpoint LSN=123456789—— 后面的数字就是redo log扫描起点,不是从头读整个日志
如果只看到Shutdown completed,说明是正常关闭,压根不走恢复流程。别把警告当恢复标志,比如InnoDB: Warning: page checksum mismatch只是校验失败提示,不代表恢复已开始。
重做阶段(Redo)到底在做什么?
这个阶段只干一件事:把redo log里所有已提交事务的物理修改,原样写回内存页或刷盘。它不解析SQL,也不关心业务逻辑。
- 日志特征:大量
Applying log record或Replaying log开头的行,紧随checkpoint LSN提示之后 - 关键节点:
redo log parsing completed出现才代表扫描结束,开始真正应用;卡在这一步,大概率是ib_logfile*损坏或磁盘I/O卡住 - 耗时取决于脏页数量和磁盘类型:SSD上通常秒级;HDD上若重做记录超百万条,可能持续数分钟
注意:redo log重做不依赖binlog,也不需要server层参与,纯InnoDB存储引擎行为。
回滚阶段(Undo)为什么经常被误读?
回滚不是执行ROLLBACK命令,而是用undo log里的前镜像(before image),反向修正内存页——这是原子性保障的核心。
- 日志特征:
Rolling back transaction或Undoing log record开头,但输出量远少于重做阶段 - 顺序不可靠:InnoDB可能并发处理多个事务回滚,日志行序≠执行顺序,别靠日志行号推断事务关系
- 中断陷阱:如果日志停在
Rolling back后无下文,大概率是某个事务的undo log页损坏,自动恢复失败,必须启用innodb_force_recovery干预
真正的“完成”标志是mysqld: ready for connections,不是Recovery completed——后者只是内部状态打印,不代表服务可用。
双重写(doublewrite)在崩溃恢复中起什么作用?
它不参与日志重放,但决定redo log能否起效:只有数据页本身完好,redo log才能安全应用。
- 崩溃后,InnoDB先加载
#ib_*.dblwr文件到内存缓冲区,逐页检查表空间中对应页的FILE_PAGE_LSN和校验和 - 若发现页损坏(比如只写入一半),就用
dblwr里的完整副本覆盖修复,再继续redo重放 - 默认开启(
innodb_doublewrite=ON),不要关;关了之后一旦页损坏,redo log直接失效,只能人工修复或丢数据
最容易被忽略的是:dblwr修复发生在redo应用之前,且修复失败时错误日志会明确报InnoDB: Database page corruption on disk——这时候自动恢复基本没戏,得立刻停机评估备份方案。











