🧑💻 面试官:MySQL 为什么有三种日志?
🙋♂️ 我:redo 用于崩溃恢复,undo 用于回滚,binlog 用于复制和恢复。
🧑💻 面试官:既然 binlog 也能恢复,为什么不能替代 redo?
🙋♂️ 我:它们记录的内容、所属层次和恢复目的不同。
🧑💻 面试官:如果 InnoDB 已经认为事务提交,但 binlog 没有这笔记录,主库和副本会怎样?两阶段提交究竟在协调谁?
这道题要抓住「不同恢复需要不同记录」:恢复数据库页、撤销事务、重放逻辑变更,不是同一件事。
面试速答(60 秒版)
redo log 是 InnoDB 的重做日志,支持在数据页尚未全部落盘时恢复相关修改。它不是 SQL 历史记录。
undo log 保存回滚所需的记录,也参与构造一致性读所需要的旧版本。事务提交以后,不代表这些记录马上就可以全部清掉。
binlog 属于 MySQL Server 层,记录逻辑变更事件,常用于复制和基于备份的时间点恢复;行格式下记录的是行变化,不一定是原始 SQL。
启用 binlog 时,内部两阶段提交协调 InnoDB 与 binlog 的事务结果:先准备,再持久化 binlog,最后完成提交。崩溃恢复会结合准备状态与 binlog 中的事务标识决定处理方式。持久化参数仍然重要,两阶段提交不能代替正确落盘配置。

知识点详解:一条更新为什么需要不同的日志?
先从“提交后数据页还没落盘”讲起
假设事务更新一条记录。InnoDB 可以先修改内存里的数据页,不必让每一次事务都立即把所有相关页写到磁盘。
那么服务器突然崩溃时,已经确认的修改可能还没有完整出现在数据文件里。redo 提供重做相关修改的依据,这属于存储引擎恢复。
InnoDB redo 文档介绍了它的作用。不要把 redo 简化成“重新执行一遍 UPDATE”,它记录的是引擎需要的重做信息。
undo 不是 redo 的反义词那么简单
事务还没提交,业务要求回滚,就需要知道怎样撤销刚才的修改。undo 保存了相应记录。
另一方面,一致性读可能需要看到旧版本。即使某次修改已经提交,仍然可能有读视图需要更早的数据,相关 undo 不能仅凭“提交了”就立即丢掉。
InnoDB undo 文档说明了回滚与多版本读取的用途。这里重点是日志职责;哪些事务版本能被哪个读视图看到,属于 MVCC 的另一道题。
binlog 记录的是对外重放的逻辑变化
复制时,副本需要知道哪些逻辑变更应该应用。恢复到某个时间点时,也可以先恢复备份,再按需要应用后续 binlog。
| 日志 | 所属位置 | 主要解决的问题 |
|---|---|---|
| redo | InnoDB | 崩溃后重做相关引擎修改 |
| undo | InnoDB | 回滚以及构造读取所需旧版本 |
| binlog | MySQL Server | 复制与逻辑变更重放 |
binlog 有不同格式。不能一律说“它完整保存每一条原始 SQL”,也不能把它当成无需备份就能从零恢复所有数据的万能文件。
redo 也不能直接代替 binlog 发给另一套库,要求它承担同样的复制语义。两者不是重复记账,而是服务不同层次。
两阶段提交,是为了避免两边对提交结果说法不同
想象两个失败顺序:
先让 InnoDB 完成提交,再写 binlog。中途崩溃,主库已经认可修改,复制记录却可能缺失。
反过来,先写出完整 binlog,再让 InnoDB 直接提交。中途崩溃,如果引擎按未提交处理,副本可能照着日志应用一笔主库后来撤掉的事务。
内部两阶段提交让引擎先进入 prepare,再写入并按配置同步 binlog,最后完成引擎提交。恢复时,准备中的事务可以结合 binlog 的有效事务记录作出决定。
MySQL 8.4 binlog 文档明确说明了准备事务与 binlog 中 xid 的恢复关系。这里讲的是简化的提交与恢复主线,实际还有组提交、日志缓冲和并发写入,不能理解成全部日志只在这三个瞬间才生成。

有两阶段提交,为什么还要设置落盘参数?
协调提交结果,不等于日志已可靠存储。缓冲区写入、操作系统缓存和磁盘持久化,仍是不同步骤。
通常会结合 innodb_flush_log_at_trx_commit=1 与 sync_binlog=1 来提高已提交事务在崩溃后的可靠性。放宽参数可能换来性能,也会改变丢失窗口。
即使配置正确,还要依赖磁盘与文件系统兑现同步语义。因此,不能许诺任何硬件故障下都绝不丢数据。副本策略、备份和恢复演练,仍然不可少。

面试官继续追问
redo 已经写了,事务就一定提交了吗?
不是。redo 中存在修改记录,与事务最终提交不是同一判断。恢复还需要考虑事务状态及必要的协调信息。
undo 会一直增加吗?
需要清理。长期事务或持续需要旧版本的读取,可能使相关记录更久不能回收,造成历史积累。排查要看事务与清理情况,不只看日志文件大小。
两阶段提交是不是应用里两个数据库的分布式事务?
这里不是。本文讨论 MySQL 内部引擎与 binlog 的协调。应用跨多个服务或数据库的事务,参与者与故障模型不同,需要另行设计。
面试速记卡
- redo:支持引擎崩溃恢复,不是 SQL 重放清单。
- undo:支持撤销和旧版本,提交不代表立即清空。
- binlog:逻辑变更事件,用于复制和结合备份恢复。
- 两阶段提交:协调引擎与 binlog 的事务结果。
- 持久化:提交协调、落盘参数与恢复演练都要考虑。
