MySQL Redo Log与Undo Log
约 1743 字大约 6 分钟
mysqlredo-logundo-log
2025-05-02
Redo Log 和 Undo Log 是 InnoDB 事务机制的两大支柱。Redo Log 保证事务的持久性(Durability),Undo Log 保证事务的原子性(Atomicity)和隔离性(通过 MVCC)。
WAL 原则
WAL(Write-Ahead Logging)是数据库领域最核心的设计原则之一:在修改数据页之前,必须先将修改记录写入日志文件并持久化到磁盘。
WAL 的核心收益是将随机写转换为顺序写:Redo Log 是追加写入的顺序文件,远比数据文件的随机 I/O 高效。
Redo Log 详解
Redo Log 结构
Redo Log 由固定数量的文件组成一个环形(circular)结构:
- Write Position:当前写入位置,不断前移
- Checkpoint:已刷脏页到磁盘的位置
- 可用空间 = Write Position 到 Checkpoint 之间的距离
- 当 Write Position 追上 Checkpoint 时,必须强制推进 Checkpoint(刷脏页)
Redo Log 配置
-- MySQL 8.0.30+ 使用动态配置
ALTER INSTANCE INNODB REDO LOG CAPACITY = 4294967296; -- 4GB
-- MySQL 8.0.30 之前
-- innodb_log_file_size = 1073741824 -- 单个文件 1GB
-- innodb_log_files_in_group = 3 -- 3 个文件
-- 总容量 = 1GB × 3 = 3GBinnodb_flush_log_at_trx_commit
这是影响 Redo Log 刷盘策略最关键的参数:
| 值 | 安全性 | 性能 | 数据丢失风险 |
|---|---|---|---|
| 1 | 最高 | 最低 | 不丢失 |
| 2 | 中等 | 中等 | OS 崩溃丢失最近 1 秒 |
| 0 | 最低 | 最高 | MySQL 崩溃丢失最近 1 秒 |
Checkpoint 机制
Checkpoint 的作用是标记 Redo Log 中哪些记录对应的脏页已经刷到磁盘,这部分 Redo Log 可以被覆盖重用。
Checkpoint 类型:
- Sharp Checkpoint:关闭数据库时,将所有脏页刷盘(
innodb_fast_shutdown=0) - Fuzzy Checkpoint:运行时增量刷新,包括:
- Master Thread 定期刷新
- LRU List 淘汰脏页时刷新
- Async/Sync Flush:Redo Log 空间不足时强制刷新
Undo Log 详解
Undo Log 的双重职责
Undo Log 类型
| 类型 | 说明 | 持续时间 |
|---|---|---|
| Insert Undo Log | INSERT 操作的回滚信息 | 事务提交后即可释放(新插入的行对其他事务不可见) |
| Update Undo Log | UPDATE/DELETE 操作的回滚信息 | 需要保留到没有事务引用该版本(支持 MVCC) |
Undo Log 与 MVCC 版本链
每行数据都有隐藏字段 DB_TRX_ID(最后修改事务 ID)和 DB_ROLL_PTR(回滚指针),通过回滚指针形成版本链:
-- 事务 100
INSERT INTO users (id, name) VALUES (1, 'Alice');
-- 事务 200
UPDATE users SET name = 'Bob' WHERE id = 1;
-- 事务 300
UPDATE users SET name = 'Charlie' WHERE id = 1;
-- 事务 150 的快照读:ReadView 中 up_limit_id=100
-- 沿版本链找到 trx_id=100 的版本 → name='Alice'Undo Tablespace
MySQL 8.0 将 Undo Log 从系统表空间独立出来:
-- 查看 Undo 表空间
SELECT * FROM information_schema.INNODB_TABLESPACES
WHERE space_type = 'Undo';
-- 默认 2 个 Undo 表空间
-- undo_001, undo_002
-- 每个表空间包含多个回滚段(Rollback Segment)
SHOW VARIABLES LIKE 'innodb_rollback_segments';
-- 默认 128
-- 支持在线 truncate
SET GLOBAL innodb_undo_log_truncate = ON;
SET GLOBAL innodb_max_undo_log_size = 1073741824; -- 1GB 触发 truncatePurge 机制
Purge 负责清理不再需要的 Undo Log 和被标记为删除的行:
-- Purge 线程数
SET GLOBAL innodb_purge_threads = 4;
-- Purge 批量处理大小
SET GLOBAL innodb_purge_batch_size = 300;
-- 查看未清理的事务数(History List Length)
SHOW ENGINE INNODB STATUS\G
-- 关注 TRANSACTIONS 部分的 History list lengthHistory List Length 过长的危害:
- Undo 表空间膨胀
- 查询性能下降(需要遍历更长的版本链)
- 可能触发事务 ID 回卷风险
Redo Log 与 Undo Log 的协作
一个完整的事务执行过程:
崩溃恢复流程
关键参数汇总
| 参数 | 默认值 | 说明 |
|---|---|---|
innodb_flush_log_at_trx_commit | 1 | Redo Log 刷盘策略 |
innodb_log_buffer_size | 16MB | Log Buffer 大小 |
innodb_redo_log_capacity | 100MB (8.0.30+) | Redo Log 总容量 |
innodb_undo_log_truncate | ON (8.0) | 自动截断 Undo 表空间 |
innodb_max_undo_log_size | 1GB | 触发 truncate 的阈值 |
innodb_rollback_segments | 128 | 回滚段数量 |
innodb_purge_threads | 4 | Purge 线程数 |
总结
- Redo Log:面向未来,记录"做了什么",保证崩溃后数据不丢失
- Undo Log:面向过去,记录"之前是什么",支持回滚和 MVCC
- WAL + Checkpoint 机制将随机写转为顺序写,是数据库高性能的关键
- 合理配置刷盘策略和日志容量,在安全性和性能之间取得平衡
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于