本章目标:理解 MySQL 核心日志体系(redo log、undo log、binlog)各自职责,掌握崩溃恢复与主从复制的基本原理。
数据库是“高并发 + 强一致 + 持久化”系统,日志是它的生命线。
日志主要解决三件事:
graph LR
A[SQL 写入请求] --> B[InnoDB 执行]
B --> C[redo log]
B --> D[undo log]
B --> E[binlog]
C --> F[崩溃恢复]
D --> G[事务回滚/MVCC]
E --> H[主从复制/数据恢复]
MySQL 写数据不是每次都立刻刷盘(随机 IO 成本高),通常先写内存页(Buffer Pool),再异步刷盘。
如果此时宕机,内存数据会丢失,所以要先有 redo log 兜底。
WAL(Write-Ahead Logging):先写日志,再写数据页。
ROLLBACK 时根据 undo log 撤销变更redo log:记录“做了什么”,用于重做undo log:记录“原来是什么”,用于撤销STATEMENT:记录原始 SQL(体积小,但部分场景不够精确)ROW:记录每行变更(更准确,主流推荐)MIXED:混合模式推荐:生产环境优先考虑 ROW。
| 日志 | 所在层 | 记录内容 | 主要用途 |
|---|---|---|---|
| redo log | InnoDB 引擎层 | 物理页变更 | 崩溃恢复,保证持久性 |
| undo log | InnoDB 引擎层 | 数据旧版本 | 回滚、MVCC |
| binlog | Server 层 | 逻辑操作/行变更 | 主从复制、增量恢复 |
sequenceDiagram
participant App as 应用
participant MySQL as MySQL
participant Redo as redo log
participant Binlog as binlog
App->>MySQL: BEGIN + UPDATE
MySQL->>Redo: 写入redo(prepare)
MySQL->>Binlog: 写入binlog
MySQL->>Redo: 写入redo(commit)
MySQL-->>App: COMMIT成功
上述流程是“两阶段提交”思想的简化表达,用于保证 redo 与 binlog 的一致性。
数据库异常宕机后,重启时会做恢复:
结果:恢复到“最近一次一致状态”。
常见恢复策略:
场景举例:
主从复制核心依赖 binlog:
graph LR
A[主库写入] --> B[主库binlog]
B --> C[从库IO线程拉取]
C --> D[relay log]
D --> E[从库SQL线程回放]
binlog 不能替代引擎级崩溃恢复能力,redo 更贴近页变更,恢复效率和语义不同。
支持 MVCC 一致性读(快照读可见性判断)。
通过 redo prepare -> binlog -> redo commit 的顺序,减少跨日志不一致风险。