Sunday 的面试指南

MySQL 的 redo log、undo log 和 binlog 有什么区别?为什么需要两阶段提交?

🧑‍💻 面试官:MySQL 为什么有三种日志?

🙋‍♂️ 我:redo 用于崩溃恢复,undo 用于回滚,binlog 用于复制和恢复。

🧑‍💻 面试官:既然 binlog 也能恢复,为什么不能替代 redo?

🙋‍♂️ 我:它们记录的内容、所属层次和恢复目的不同。

🧑‍💻 面试官:如果 InnoDB 已经认为事务提交,但 binlog 没有这笔记录,主库和副本会怎样?两阶段提交究竟在协调谁?

这道题要抓住「不同恢复需要不同记录」:恢复数据库页、撤销事务、重放逻辑变更,不是同一件事。

面试速答(60 秒版)

redo log 是 InnoDB 的重做日志,支持在数据页尚未全部落盘时恢复相关修改。它不是 SQL 历史记录。

undo log 保存回滚所需的记录,也参与构造一致性读所需要的旧版本。事务提交以后,不代表这些记录马上就可以全部清掉。

binlog 属于 MySQL Server 层,记录逻辑变更事件,常用于复制和基于备份的时间点恢复;行格式下记录的是行变化,不一定是原始 SQL。

启用 binlog 时,内部两阶段提交协调 InnoDB 与 binlog 的事务结果:先准备,再持久化 binlog,最后完成提交。崩溃恢复会结合准备状态与 binlog 中的事务标识决定处理方式。持久化参数仍然重要,两阶段提交不能代替正确落盘配置。

MySQL 三种日志:职责不同

知识点详解:一条更新为什么需要不同的日志?

先从“提交后数据页还没落盘”讲起

假设事务更新一条记录。InnoDB 可以先修改内存里的数据页,不必让每一次事务都立即把所有相关页写到磁盘。

那么服务器突然崩溃时,已经确认的修改可能还没有完整出现在数据文件里。redo 提供重做相关修改的依据,这属于存储引擎恢复。

InnoDB redo 文档介绍了它的作用。不要把 redo 简化成“重新执行一遍 UPDATE”,它记录的是引擎需要的重做信息。

undo 不是 redo 的反义词那么简单

事务还没提交,业务要求回滚,就需要知道怎样撤销刚才的修改。undo 保存了相应记录。

另一方面,一致性读可能需要看到旧版本。即使某次修改已经提交,仍然可能有读视图需要更早的数据,相关 undo 不能仅凭“提交了”就立即丢掉。

InnoDB undo 文档说明了回滚与多版本读取的用途。这里重点是日志职责;哪些事务版本能被哪个读视图看到,属于 MVCC 的另一道题。

binlog 记录的是对外重放的逻辑变化

复制时,副本需要知道哪些逻辑变更应该应用。恢复到某个时间点时,也可以先恢复备份,再按需要应用后续 binlog。

日志所属位置主要解决的问题
redoInnoDB崩溃后重做相关引擎修改
undoInnoDB回滚以及构造读取所需旧版本
binlogMySQL 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 的事务结果。
  • 持久化:提交协调、落盘参数与恢复演练都要考虑。
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历