MySQL Undo Log vs Redo Log

mysql数据库如何实现数据一致性(崩溃异常情况下数据不丢失), redo + undo来保证。

1.MySQL Undo Log vs Redo Log

在 InnoDB 存储引擎中:

  • Undo Log(回滚日志)
    解决:

    • 事务回滚(Rollback)
    • MVCC(多版本并发控制)
    • 一致性读(快照读)
  • Redo Log(重做日志)
    解决:

    • 崩溃恢复(Crash Recovery)
    • 持久化(Durability)
    • WAL(Write Ahead Logging)

二者属于 InnoDB 事务系统的核心。


2.核心区别

对比项 Undo Log Redo Log
中文 回滚日志 重做日志
作用 撤销数据 重做数据
方向 逻辑逆操作 物理页修改
用途 回滚/MVCC 崩溃恢复
生命周期 事务结束后可清理 checkpoint后可覆盖
存储内容 修改前数据 修改后页变更
是否持久化
属于 事务层 存储引擎恢复层
是否用于MVCC
是否提升写性能 间接 直接核心作用

3.Undo Log 工作机制

3.1 本质

Undo Log 保存:数据修改之前的旧版本。

例如:

1
UPDATE user SET age=20 WHERE id=1;

修改前:

1
age=18

Undo 中记录:把 age 从20恢复成18


3.2 回滚流程(undo log)

事务:

1
2
3
4
5
BEGIN;

UPDATE account SET money=500 WHERE id=1;

ROLLBACK;

回滚时:

1
2
Undo Log:
money: 500 -> 1000

InnoDB 根据 undo 反向恢复数据。


3.3 MVCC核心

Undo Log 还承担:

快照读

事务A:

1
2
BEGIN;
SELECT * FROM user;

事务B:

1
2
UPDATE user SET age=30;
COMMIT;

事务A依然可能读到旧数据。

原因:

1
旧版本保存在 Undo Log

MVCC链:

1
2
3
4
5
6
7
最新行

undo version 1

undo version 2

undo version 3

4.Redo Log 工作机制

4.1 本质

Redo Log 保存:页修改操作不是SQL。

例如:

1
UPDATE user SET age=20 WHERE id=1;

Redo可能记录:

1
2
page 10 offset 200:
18 -> 20

属于物理日志。


4.2 为什么需要Redo

如果每次事务提交都:

1
直接刷磁盘数据页

代价极大:

  • 随机IO
  • 数据页16KB
  • 磁盘寻址慢

因此 InnoDB WAL机制(Write Ahead Logging)

流程:

1
2
先写 redo log
后刷数据页

因为 redo log:

  • 顺序写
  • append写
  • 非常快

5.Redo Crash Recovery

5.1 崩溃场景

事务:

1
COMMIT;

此时:

1
2
redo已落盘
数据页还没刷盘

机器断电。


5.2 启动恢复

MySQL 重启:扫描 redo log,重新执行页修改恢复数据。这就是:crash-safe


6.Undo 与 Redo协同

真正事务提交流程:

flowchart LR

A[修改Buffer Pool] --> B[记录Undo]
B --> C[记录Redo]
C --> D[提交事务]
D --> E[Redo fsync]
E --> F[后台刷脏页]

7.为什么两种日志都必须存在

7.1 只有Redo不行

无法:

  • 回滚
  • MVCC
  • 快照读

因为 redo 只有“怎么改”。没有“改之前是什么”。


7.2 只有Undo不行

无法:

  • 崩溃恢复
  • 保证持久化

因为:内存脏页可能没落盘,数据库重启后数据丢失。


8.事务提交全过程(核心)

事务:

1
2
3
BEGIN;
UPDATE user SET age=20 WHERE id=1;
COMMIT;

执行过程:

Step1 修改Buffer Pool

内存页修改:

1
18 -> 20

Step2 写Undo(修改前数据)

记录:

1
20 -> 18

Step3 写Redo Buffer

记录:

1
page修改

Step4 COMMIT

触发:

1
redo buffer -> redo file

fsync。


Step5 返回客户端成功

此时:

即使机器断电:

1
redo仍能恢复

Step6 后台Checkpoint

异步刷:

1
脏页 -> ibd文件

9.对应磁盘文件

9.1 Undo

MySQL 8:

1
undo tablespace

文件:

1
2
undo_001
undo_002

或者:

1
ibdata1

历史版本。


9.2 Redo

文件:

1
#innodb_redo/

MySQL 8 新格式。

旧版本:

1
2
ib_logfile0
ib_logfile1