Redo Log与Undo Log
Redo Log和Undo Log是InnoDB保证事务ACID特性的核心机制。
Redo Log(重做日志)
核心作用
- 保证事务持久性(Durability)
- 崩溃恢复时重放已提交事务
- WAL(Write-Ahead Logging)核心组件
存储结构
SQL
┌─────────────────────────────────────────────────┐
│ Redo Log架构 │
├─────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Log Buffer │ ──→ │ Redo Log Files │ │
│ │ (内存中) │ │ ib_logfile0/1 │ │
│ └─────────────┘ └─────────────────────┘ │
│ ↑ ↑ │
│ 事务写入 顺序写入 │
└─────────────────────────────────────────────────┘
循环写入机制
SQL
ib_logfile0 ib_logfile1
┌──────────────┐ ┌──────────────┐
│ →→→→→→→→→→→→→→→→→→→→→│→→→→→→→→→→→→→→│
└──────────────┘ └──────────────┘
↑ ↑
write pos check point
(当前写入位置) (检查点位置)
已使用空间 = write pos - check point
可用空间 = 总大小 - 已使用空间
写入流程
SQL
1. 事务修改数据
↓
2. 记录修改到Redo Log Buffer
↓
3. 根据策略刷入Redo Log文件
↓
4. 提交事务(Commit)
关键参数
SQL
-- Redo Log刷盘策略(0/1/2)
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
-- 值说明
-- 0: 每秒刷盘,崩溃可能丢失1秒数据
-- 1: 每次提交刷盘,最安全(默认)
-- 2: 每次提交写入OS缓存,每秒刷盘
-- Redo Log文件大小
SHOW VARIABLES LIKE 'innodb_log_file_size';
-- Redo Log文件数量
SHOW VARIABLES LIKE 'innodb_log_files_in_group';
-- Log Buffer大小
SHOW VARIABLES LIKE 'innodb_log_buffer_size';
刷盘策略对比
| 值 | 刷盘时机 | 性能 | 安全性 |
|---|---|---|---|
| 0 | 每秒刷盘 | 最高 | 最低(可能丢1秒数据) |
| 1 | 每次提交刷盘 | 最低 | 最高(默认) |
| 2 | 提交写OS缓存,每秒刷盘 | 中等 | 中等 |
Undo Log(回滚日志)
核心作用
- 保证事务原子性(Atomicity)
- 支持事务回滚
- 支持MVCC多版本读
存储结构
text
Undo Log存储在系统表空间或独立Undo表空间
┌─────────────────────────────────────┐
│ Undo Log记录 │
├─────────────────────────────────────┤
│ trx_id: 事务ID │
│ roll_ptr: 回滚指针 │
│ undo_type: 操作类型(INSERT/UPDATE) │
│ old_values: 修改前的数据 │
└─────────────────────────────────────┘
数据行隐藏列
text
每行数据包含隐藏列:
┌────────┬──────────┬───────────┐
│ DB_TRX_ID │ DB_ROLL_PTR │ DB_ROW_ID │
│ 事务ID │ 回滚指针 │ 行ID │
│ (6字节) │ (7字节) │ (6字节) │
└────────┴──────────┴───────────┘
版本链示意
text
当前数据行 ←── DB_ROLL_PTR ──→ Undo Log记录1
↓
Undo Log记录2
↓
Undo Log记录3
↓
历史版本
MVCC读取流程
text
1. 事务开始,获取Read View
↓
2. 根据DB_TRX_ID判断可见性
↓
3. 不可见 → 通过DB_ROLL_PTR找Undo Log
↓
4. 遍历版本链直到找到可见版本
↓
5. 返回该版本数据
Undo Log类型
| 类型 | 适用操作 | 存储内容 |
|---|---|---|
| insert undo log | INSERT | 主键值 |
| update undo log | UPDATE/DELETE | 修改前数据 |
两者的协作关系
事务提交流程
text
┌─────────────────────────────────────────────────┐
│ 事务提交流程 │
├─────────────────────────────────────────────────┤
│ 1. 修改数据,写入Buffer Pool │
│ ↓ │
│ 2. 记录Undo Log(修改前数据) │
│ ↓ │
│ 3. 记录Redo Log(修改操作) │
│ ↓ │
│ 4. 修改Buffer Pool中的数据页 │
│ ↓ │
│ 5. 写入Redo Log Buffer │
│ ↓ │
│ 6. 根据策略刷入Redo Log文件 │
│ ↓ │
│ 7. 提交成功 │
└─────────────────────────────────────────────────┘
崩溃恢复流程
text
1. 数据库启动
↓
2. 检查Redo Log
↓
3. 重放(Redo)已提交但未刷盘的事务
↓
4. 回滚(Undo)未提交的事务
↓
5. 恢复完成
性能优化
Redo Log优化
text
-- 高并发写入场景
SET innodb_log_file_size = 512M; -- 增大日志文件
SET innodb_log_buffer_size = 64M; -- 增大缓冲区
-- 追求性能可接受少量数据丢失
SET innodb_flush_log_at_trx_commit = 2;
Undo Log优化
text
-- 使用独立Undo表空间(MySQL 8.0+)
SHOW VARIABLES LIKE 'innodb_undo_tablespaces';
-- Undo日志保留时间(用于长事务回滚)
SHOW VARIABLES LIKE 'innodb_max_undo_log_size';
监控指标
text
-- Redo Log状态
SHOW STATUS LIKE 'Innodb_os_log_written';
SHOW STATUS LIKE 'Innodb_log_waits';
-- Undo Log状态
SHOW STATUS LIKE 'Innodb_undo_log_active';
SHOW STATUS LIKE 'Innodb_undo_log_expunge';
要点总结
- Redo Log保证持久性,崩溃恢复时重放已提交事务
- Undo Log保证原子性,支持回滚和MVCC
- Redo Log采用循环写入,WAL机制提升性能
- Undo Log通过版本链实现MVCC,支持一致性非锁定读
innodb_flush_log_at_trx_commit=1是默认最安全设置- 合理配置日志大小和刷盘策略,平衡性能与可靠性
📝 发现内容有误?点击此处直接编辑