你是否曾好奇:在APP上完成一笔支付,点击确认的瞬间手机突然黑屏,重启后发现支付竟然成功了;或者数据库服务器意外宕机,重启后数据却完好无损?
这背后并非运气,而是MySQL中三位至关重要的“隐形守护者”在协同工作——Undo Log、Redo Log 和 Binlog。它们各司其职又紧密配合,不仅确保了事务的ACID特性,更支撑着亿级流量的主从复制架构。本文将以一条更新语句为例,深入浅出地为你揭示这三者如何精密协作。
先识其面:三大日志的核心角色
Undo Log 是 InnoDB 存储引擎特有的日志,主要服务于事务的原子性(要么全部完成,要么全部回滚)和隔离性(通过 MVCC 实现读写不冲突)。它记录的是数据被修改之前的原始值。例如,将 age=4 改为 age=3,Undo Log 就会记录下 age=4。它属于逻辑日志。
通俗地说,Undo Log 就像编辑文档前按下的“Ctrl+Z”备份,一旦操作失误或事务回滚,就能用它快速恢复原状。

Redo Log 同样是 InnoDB 引擎的日志,其核心使命是保障事务的持久性(事务一旦提交,数据变更必须永久保存)。它记录的是数据页的物理修改信息,比如“在数据文件第100页第5个偏移量处写入字节‘Li’”。它也属于物理日志。
你可以将其理解为一个“流水账本”。在数据库中,为了提高性能,数据总是先在内存(Buffer Pool)中修改,再异步刷回磁盘。Redo Log 就负责记录这些内存中的修改。即使系统突然崩溃,重启后也能根据 Redo Log 重做这些操作,确保已提交事务的修改不丢失。这背后依赖的是 WAL(Write-Ahead Logging,预写式日志) 技术。

Binlog(二进制日志)是 MySQL Server 层提供的日志,所有存储引擎都可以使用。它的主要作用是主从复制和数据恢复。它记录的是所有对数据库产生变更的 SQL 语句(Statement 格式)或行数据的变化(Row 格式),属于逻辑日志。
它就像一个不可篡改的“操作档案”。主库将 Binlog 发送给从库,从库重放这些日志即可实现数据同步;此外,当需要将数据库恢复到某个历史时间点时,Binlog 也是关键依据。

观其协作:一条Update语句的完整旅程
理论说再多不如实战。现在,我们以一条简单的 SQL 语句 UPDATE user SET name = 'Li' WHERE id = 1;(假设原 name 为 'Wang')为例,拆解三大日志的完整协作流程。
第一阶段:执行修改,预留退路
- 加载数据:InnoDB 引擎首先将
id=1 所在的数据页从磁盘加载到内存的 Buffer Pool 中。
- 写入 Undo Log:在真正修改内存数据前,引擎会生成一条 Undo Log,记录“
id=1 的 name 原值是 Wang”。这里有一个精妙配合:写入 Undo Log 这个操作本身,也会被记录到 Redo Log 中,为“后悔药”本身加上保险。
- 更新内存:在 Buffer Pool 中将
name 字段修改为 'Li'。此时,内存中的数据页与磁盘上的版本不一致,成为了“脏页”。

第二阶段:两阶段提交,确保一致(核心!)
这时面临一个关键问题:Redo Log 在引擎层,Binlog 在 Server 层,如何保证两者记录的事务操作绝对一致? 绝不能出现“Redo Log 说改了,Binlog 说没改”的情况,否则主从数据必然不一致。
答案就是 两阶段提交(2 Phase Commit, 2PC),它像是引擎层与 Server 层之间的一次可靠握手:
-
Prepare 阶段(Redo Log Prepare):
- 引擎将本次事务相关的所有 Redo Log 写入磁盘文件。
- 写入后,将这些 Redo Log 记录的状态标记为
PREPARE。此时,引擎层已准备就绪,等待 Server 层的最终指令。
-
Commit 阶段:
- 写入 Binlog:MySQL Server 层将本条
UPDATE 语句的 Binlog 写入磁盘。一旦 Binlog 成功落盘,意味着该操作在逻辑上已永久生效,并可以被同步到从库。
- 提交 Redo Log:Server 层通知 InnoDB 引擎:“Binlog 已写完毕”。引擎随即把对应 Redo Log 记录的状态从
PREPARE 更新为 COMMIT。至此,整个事务提交过程才正式完成。

懂其原理:崩溃恢复的两种关键场景
两阶段提交的设计,正是为了应对崩溃恢复的复杂场景。MySQL 重启后,会严格检查 Redo Log 和 Binlog 的状态来决定事务的最终命运:
一张表看清:三大日志核心差异
| 特性 |
Redo Log (重做日志) |
Binlog (二进制日志) |
Undo Log (回滚日志) |
| 所属层面 |
InnoDB 存储引擎层 |
MySQL Server 层 |
InnoDB 存储引擎层 |
| 记录内容 |
物理日志(数据页的修改) |
逻辑日志(SQL语句或行变化) |
逻辑日志(修改前的反向操作) |
| 写入时机 |
事务进行中持续写入 |
事务提交时一次性写入 |
数据修改前写入 |
| 核心功能 |
Crash-Safe,保证事务持久性 |
主从复制、数据备份恢复 |
事务回滚(原子性)、MVCC(隔离性) |
| 空间管理 |
循环写入(固定大小文件组) |
追加写入(文件达到大小后切换) |
存放在回滚段,事务提交后可清理 |
核心总结:协同工作的精髓
最后,我们用四句话来概括三大日志协同的精髓:
- Undo Log 赋予事务“反悔权”,支撑回滚与 MVCC,是数据的安全垫。
- Redo Log 依托 WAL 技术,让内存高速操作无惧断电,是数据的持久保障。
- Binlog 充当数据流通的桥梁,连接主从复制与备份恢复生态。
- 两阶段提交是三者协同的枢纽,它强制对齐 Redo Log 与 Binlog,是确保数据最终一致性与 MySQL Crash-Safe 能力 的基石。
本质上,这三种日志的设计是数据库在 “极致性能” 与 “绝对可靠” 之间做出的精妙权衡——用内存操作提升速度,用多级日志保障安全。透彻理解它们的配合机制,你对 MySQL 高可用架构的认知也将更加深刻。
|