MySQL 的 binlog、redo log 和 undo log 是数据库事务处理与数据一致性的核心组件,各自承担不同的职责。
1. binlog(二进制日志)
- 定位:MySQL Server 层实现的逻辑日志,与存储引擎无关。
- 作用:
- 主从复制:记录所有数据库表结构变更和表数据修改的 SQL 语句(如
INSERT
/UPDATE
/DELETE
)或行变更事件,用于同步数据到从库。 - 数据恢复:通过
mysqlbinlog
工具解析 binlog,恢复误删除的数据或执行时间点恢复(Point-in-Time Recovery)。
- 主从复制:记录所有数据库表结构变更和表数据修改的 SQL 语句(如
- 特点:
- 逻辑记录:记录的是 SQL 语句或行变更的逻辑操作(如
UPDATE user SET name='Alice' WHERE id=1
)。 - 追加写入:以事件(Event)形式按顺序写入文件,文件大小可配置(如
max_binlog_size
)。 - 事务性:支持事务的完整性,通过
sync_binlog
参数控制刷盘策略。
- 逻辑记录:记录的是 SQL 语句或行变更的逻辑操作(如
- 工作流程:
- 事务提交时,将 SQL 语句或行变更事件写入 binlog。
- 从库通过 I/O 线程读取主库的 binlog,重放(Replay)这些事件实现数据同步。
2. redo log(重做日志)
- 定位:InnoDB 存储引擎特有的物理日志,保证事务的持久性(ACID 中的 D)。
- 作用:
- 崩溃恢复:确保事务提交后,即使系统崩溃,修改的数据不会丢失。
- Write-Ahead Logging (WAL):修改数据前先写日志,避免每次写操作都直接刷盘(提升性能)。
- 特点:
- 物理记录:记录的是数据页(Page)的物理修改(如“在表空间第5页偏移量100处写入数据”)。
- 循环写入:固定大小的文件组(如
ib_logfile0
、ib_logfile1
),循环覆盖使用。 - 持久化控制:通过
innodb_flush_log_at_trx_commit
参数控制刷盘频率(1:每次提交刷盘;0/2:延迟刷盘)。
- 工作流程:
- 事务执行时,修改数据页前先将变更记录到 redo log。
- 事务提交时,redo log 按策略刷盘。
- 崩溃恢复时,重放 redo log 中的操作,将未刷盘的数据页更新到磁盘。
3. undo log(回滚日志)
- 定位:InnoDB 存储引擎的逻辑日志,支持事务回滚和 MVCC(多版本并发控制)。
- 作用:
- 事务回滚:记录事务修改前的数据快照,用于回滚未提交的事务。
- MVCC 实现:提供数据的历史版本,支持非锁定读(如
SELECT
查询读取旧版本数据)。
- 特点:
- 逻辑记录:存储旧版本数据的逻辑快照(如
UPDATE
前的行数据)。 - 版本链:通过
ROLL_PTR
指针形成多版本链,支持事务隔离级别(如 RR 和 RC)。 - 存储位置:存放在共享表空间或独立 undo 表空间(
innodb_undo_directory
)。
- 逻辑记录:存储旧版本数据的逻辑快照(如
- 工作流程:
- 事务修改数据前,生成 undo log 记录旧数据。
- 事务回滚时,根据 undo log 恢复原始数据。
- MVCC 查询时,通过 undo log 版本链找到可见的数据版本。
三者的协作关系
事务提交过程(两阶段提交)
- Prepare 阶段:
- InnoDB 将事务的 redo log 写入内存并刷盘(
prepare
状态)。
- InnoDB 将事务的 redo log 写入内存并刷盘(
- Commit 阶段:
- MySQL Server 将事务的 binlog 写入磁盘。
- InnoDB 将 redo log 标记为
commit
状态,完成事务提交。
通过两阶段提交(2PC)保证 binlog 和 redo log 的一致性,避免主从不一致或数据丢失。
崩溃恢复
- 检查 redo log 中是否存在
prepare
状态的日志。 - 若存在,检查 binlog 中是否有对应事务的完整记录:
- 如果 binlog 完整,提交事务(重放 redo log)。
- 如果 binlog 不完整,回滚事务(使用 undo log)。
对比总结
日志类型 | 层级 | 内容 | 核心作用 | 持久化控制参数 |
---|---|---|---|---|
binlog | MySQL Server 层 | 逻辑日志(SQL/行变更) | 主从复制、数据恢复 | sync_binlog |
redo log | InnoDB 引擎层 | 物理日志(页修改) | 崩溃恢复、事务持久性 | innodb_flush_log_at_trx_commit |
undo log | InnoDB 引擎层 | 逻辑日志(数据快照) | 事务回滚、MVCC 多版本读 | innodb_undo_log_truncate |
常见问题
Q1:为什么需要 redo log 和 binlog 同时存在?
- redo log:确保 InnoDB 引擎层的事务持久性,物理日志更高效。
- binlog:MySQL Server 层的逻辑日志,支持主从复制和跨引擎数据恢复。
Q2:undo log 会被删除吗?
- 当事务提交且没有其他事务需要依赖其旧版本时,undo log 会被清理(如通过 Purge 线程)。
Q3:如何优化日志性能?
- binlog:设置
sync_binlog=0
(由系统决定刷盘)或批量提交事务。 - redo log:设置
innodb_flush_log_at_trx_commit=2
(每秒刷盘)。 - undo log:使用独立表空间并定期清理。
总结
- binlog:逻辑日志,面向主从复制和数据恢复。
- redo log:物理日志,面向崩溃恢复和事务持久性。
- undo log:逻辑日志,面向事务回滚和 MVCC。
三者协同工作,保障了 MySQL 的事务 ACID 特性、高可用性和数据一致性。