redo log、undo log 与 binlog 各有什么作用,如何协同完成事务?

考查重点:日志职责与提交协调。undo 回滚/版本,redo 恢复,binlog 复制与逻辑恢复;两阶段提交协调 redo/binlog 的提交决定

本题目录

参考答案

核心回答

以 MySQL 8.4、InnoDB 普通持久表,并开启 binlog 为例,三类日志各有分工:undo log 支持回滚和历史版本读取,redo log 支持崩溃恢复,binlog 记录可供复制与备份恢复的数据变更。 提交时,MySQL 通过内部两阶段提交,让 InnoDB 的提交结果与 binlog 中的事务记录保持一致;undo 并不是其中独立的第三个提交阶段。

  • undo log 保存撤销修改所需的信息,例如更新前的列值。事务回滚时用它撤销修改;一致性读也可以沿版本链构造符合 Read View 的历史记录。它不是简单保存一条“反向 SQL”,提交后也不一定立即清理,其他事务可能仍需要旧版本。
  • redo log 记录 InnoDB 数据页相关的修改,使数据库能在崩溃后重做尚未完整写入数据文件的变化。它配合 WAL:脏页写入数据文件前,相关 redo 必须先满足持久化要求,因此提交不必等待所有修改过的数据页都写盘。
  • binlog 位于 MySQL Server 层,以事件记录数据变更,主要用于复制,以及恢复备份之后继续重放增量。它可以采用 ROW、STATEMENT 等格式;ROW 记录行变化,不能把所有 binlog 都说成原始 SQL。它也不能代替 InnoDB 的页级崩溃恢复。

可以把三者理解为:undo 负责“需要撤销或读取旧版本时怎么办”,redo 负责“内存里的页修改还没完全落到数据文件时怎么办”,binlog 负责“怎样把已记录的数据变更用于其他实例或历史恢复”。

一次事务怎样使用这些日志

假设事务把一条余额记录从 100 改为 80。执行期间,InnoDB 记录撤销所需的信息,修改 Buffer Pool 中的数据页,并产生相应 redo;持久表的 undo 页修改本身也需要 redo 保护。Server 层则收集该事务对应的 binlog 事件,通常先放在事务缓存中。

redo 可以在事务尚未提交时写出,数据页也可能在事务结束前被刷出。因此不能用“日志或数据页已写盘”直接判断事务已经提交。最终是否保留这些修改,还要结合事务提交状态;未提交的修改可以借助 undo 撤销。

在常见的耐久配置下,提交的逻辑过程是:

  1. InnoDB 准备事务。 记录 prepare 状态,保留后续提交或回滚所需的信息,并保证在需要作出耐久提交决定前,相关 redo 已经可靠保存。
  2. Server 写入并同步完整 binlog 事务。 事务事件及相应的 XID 提交记录构成恢复时的提交依据。只有写到文件系统缓存,还不等于已经耐久保存。
  3. InnoDB 完成提交。 根据协调结果提交事务,随后向客户端返回结果。数据页可以再由后台逐步刷盘,不要求在这个阶段全部写完。

这里描述的是事务协调的先后关系。实际实现有组提交等机制,可以合并多个事务的日志写入或同步,不能据此推导每个事务必然独占固定次数的 fsync。

两阶段提交怎样处理崩溃

如果分别完成 redo 提交和 binlog 写入,中间宕机就可能出现“本地恢复保留了修改,但复制或备份恢复没有这次修改”,或者相反的结果。内部两阶段提交保留 prepare 状态,让恢复过程能够作出同一决定。

对于崩溃后仍处于 prepared 状态的内部事务,关键看有效、完整且持久保存的 binlog 中,是否存在对应 XID 的提交记录:

  • 没有对应提交记录:不能把它当作已经提交的事务,应回滚其修改。
  • 存在对应提交记录:即使 InnoDB 的最终 commit 记录尚未完成,也可以继续完成提交,使本地结果与 binlog 一致。

恢复时,redo 会先帮助恢复需要的数据页状态,再结合事务状态与 undo 处理未完成事务。不能简单地说“redo 中的内容全部算已提交”,也不能只看到一个孤立 XID 就忽略事务记录是否完整有效。

持久化配置影响什么

通常所说的“双 1”是 innodb_flush_log_at_trx_commit=1 和 sync_binlog=1:前者要求提交相关的 redo 写入并同步,后者要求同步 binlog 提交组。它们是保证本地崩溃恢复与日志一致性的重要条件,但仍依赖操作系统和存储设备正确兑现同步请求。

放宽这些配置,可以减少同步开销,也可能丢失已经向客户端确认的事务或相应日志。两阶段提交解决的是提交协调,不能把尚在易失缓存中的数据自动变成耐久数据,更不能保证副本已经执行完成。

常见追问

为什么有 binlog 还需要 redo?

binlog 面向数据变更的复制和重放,不负责直接修复 InnoDB 数据文件里哪些页更新到了一半。redo 与检查点、数据页和引擎恢复过程配合,解决的是本地存储恢复问题;备份加 binlog 的历史恢复是另一条路径。

undo 在提交后为什么还会占空间?

回滚不再需要,不代表历史读取也不再需要。部分 undo 仍可能被活跃事务的一致性读使用,要等不再需要后才能清理。长事务可能延长历史版本保留时间。

客户端提交超时,能认定事务失败吗?

不能。事务可能已经完成耐久提交,只是响应没到客户端。应通过稳定的业务标识查询结果,必要时幂等重试,不能根据网络超时直接重复执行扣款等动作。数据库内部两阶段提交也不等于已经解决跨服务的分布式事务。

参考资料

相关面经

10 篇

腾讯音乐

后端开发工程师
秋招一面
查看原面经 →
MySQL 中的 redo log、undo log、binlog 分别是什么?有什么作用?

字节跳动

后端开发工程师
一面
查看原面经 →
MySQL 为什么需要两阶段提交?redo log 和 binlog 如何协调,故障后如何恢复?

钛松科技

后端开发工程师
查看原面经 →
InnoDB 崩溃恢复日志有哪些?

百度

Agent 应用开发工程师
秋招一面
查看原面经 →
binlog、undo log 和 redo log 分别有什么作用?

小红书

AI Native 全栈开发工程师
日常实习一面、二面
查看原面经 →
redo log 与 binlog 区别
redo log + binlog 两阶段提交
展开剩余 5 篇面经

蚂蚁集团

Agent 开发工程师
秋招一面
查看原面经 →
MySQL中的redo log、undo log、binlog分别有什么作用?三者之间有什么区别?

影石创新

AI Agent
实习一面
查看原面经 →
MySQL中的undo log、redo log和binlog分别解决什么问题?它们之间有什么区别?
什么是MySQL两阶段提交?为什么需要这个机制?

字节跳动

AI 应用开发
一面
查看原面经 →
mysql的undolog,redolog,binlog区别和场景?(开始吟唱)
什么是两阶段提交?(吟唱八股)

高德

Agent 后端开发
日常实习一面
查看原面经 →
e. 了解数据库里面的Binlog、Redolog之类吗?

美团

后端开发
日常实习一面
查看原面经 →
了解过 Undolog 和 Redolog 吗?

收录题集

2 个来源,共2 份题集

相关题目

4 题