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 时每次提交刷盘,保证数据不丢。