Skip to content

P25 Mysql 怎么做到 Redo Log 崩溃恢复的? ​

面试题:MySQL 崩溃后怎么保证数据不丢?redo log 的崩溃恢复原理是什么?

1. 为什么需要 redo log ​

InnoDB 写数据是先改 Buffer Pool 内存页,后台异步刷盘。如果刚改完内存还没刷盘就断电/崩溃,内存里的修改会丢。所以用 WAL(Write-Ahead Logging):

text
先写 redo log(磁盘,顺序写很快)→ 再改内存页 → 异步刷盘

崩溃后根据 redo log 重放(redo) 未刷盘的修改,数据就不丢。

2. redo log 是什么 ​

  • 物理日志:记录"在哪个页、哪个偏移、改成了什么";
  • 大小固定、循环写:ib_logfile0、ib_logfile1...(默认 48MB×2 之类,可配置);
  • 有 LSN(Log Sequence Number) 单调递增,用于定位日志写到哪、数据刷到哪。

3. 崩溃恢复过程(三步) ​

text
① 扫描 redo log:确定从哪个 LSN 开始恢复
② 重放(redo):把日志里的修改重新应用到对应的数据页(内存/磁盘)
③ 未提交事务的修改会通过 undo log 回滚(保证原子性)

具体:

  • redo log 有 checkpoint(检查点)概念:checkpoint 之前的日志对应修改已刷盘,可以覆盖;
  • 崩溃后从 checkpoint 之后的 LSN 开始重放,直到日志末尾;
  • 配合 undo log:已 commit 的重放保留,未 commit 的回滚。

4. 关键参数 ​

text
innodb_flush_log_at_trx_commit
值行为可靠性性能
1(默认)每次提交都刷盘最安全,最多丢一个事务(不丢)最慢
2提交时写 OS 缓存,每秒刷盘系统崩溃丢 1 秒数据较快
0每秒刷盘可能丢 1 秒数据最快

生产默认用 1。

加分点 ​

  • redo log 是 InnoDB 引擎层的日志,binlog 是 Server 层的日志,二者配合两阶段提交保证崩溃恢复 + 主从一致;
  • redo log 顺序写、组提交(group commit)是高性能的关键;
  • 追问"为什么比直接刷数据页快":日志是顺序小写,数据页是随机大 IO。

一句话总结 ​

InnoDB 用 WAL:先顺序写 redo log 再改内存页,崩溃后从 checkpoint 处重放 redo log 恢复未刷盘的修改,未提交事务用 undo log 回滚;innodb_flush_log_at_trx_commit=1 时每次提交刷盘,保证数据不丢。

基于 VitePress 重建