【MySQL | 第13篇】Redo Log、Binlog 之间的联系与「两阶段提交」的底层逻辑

在这里插入图片描述

在 MySQL 的面试和学习中,redo log(重做日志)和 binlog(归档日志)是绕不开的绝对核心。直观的记忆是,他们“一个是物理日志,一个是逻辑日志”,但在一些深入的拷打中,还有更多的细节和联系

本文对比 redolog、binlog,从日志架构中最让人困惑的三个痛点,梳理底层的推导逻辑。


痛点一:为什么写的方式一个是“循环”,一个是“追加”?

虽然我们已经知道 redo log 是循环写,binlog 是追加写。但为什么要这么设计?这取决于它们各自的历史使命

1. Redo Log:防崩溃(循环写)

  • 使命:保证事务的持久性。它记录的是“内存里的数据页改了什么,但还没来得及刷入磁盘的数据”。
  • 为什么循环写?
    一旦 MySQL 的后台线程把内存里的脏页真正刷入了磁盘(落盘),这部分 redo log 就彻底失去价值了(因为数据已经安全躺在磁盘里了)。
    既然没用了,就不需要无限期保留。所以 InnoDB 把它设计成固定大小(比如 4 个 1GB 的文件),像一个环形空间,前面的数据落盘了,后面的新日志就可以直接覆盖上来。这样极大地节省了磁盘空间。

2. Binlog:主从同步与恢复(追加写)

  • 使命:主从同步(Replication)和数据备份恢复(比如把数据库恢复到半个月前的任意一秒)。
  • 为什么追加写?
    它记录的是数据库的所有历史变更逻辑历史是绝对不能被覆盖的! 如果覆盖了,你怎么把数据库恢复到昨天下午 3 点?你怎么让新接入的从库同步全量数据?
    所以,binlog 必须是一个文件写满了,就新建下一个文件,永远追加(Append),绝不覆写旧数据。

痛点二:为什么必须是“两阶段提交”?

执行一个更新事务时,InnoDB 需要写 redo log,Server 层需要写 binlog。既然要写两份日志,为什么非要搞一个复杂的“两阶段提交(2PC)”?

比如针对这样的问题:“如果不使用两阶段提交,到底会引发什么灾难?”
我们来做个逻辑推导:

假设没有两阶段提交,只有两种执行顺序:

  • 方案 A:先写 redo log,再写 binlog。

    • 灾难现场:redo 写完了,机器突然断电宕机,binlog 还没来得及写。
    • 后果:机器重启后,InnoDB 引擎通过 redo log 把这条数据恢复了(主库有了这条新数据)。但是因为没有 binlog,这条变更永远不会同步给从库。导致主库多了一条数据,主从数据不一致
  • 方案 B:先写 binlog,再写 redo log。

    • 灾难现场:binlog 写完了,机器断电宕机,redo 还没写。
    • 后果:机器重启后,因为没有 redo log,主库无法恢复这条变更(主库丢失了这条数据)。但是 binlog 已经写完了,从库拿到 binlog 并执行了同步。导致从库多了一条数据,主从数据依然不一致

结论:无论是先写谁,只要中间发生崩溃,都会导致主库和从库的数据割裂。为了解决这个问题,MySQL 必须把这两个操作绑定在一起,做到 “要么一起成功,要么一起失败”,这就是两阶段提交诞生的根本原因。


痛点三:崩溃恢复时的判定逻辑(XID 是关键)

知道了为什么要两阶段提交,那它到底是怎么工作的?在发生崩溃重启时,MySQL 又是如何精准判定一个事务该提交还是该回滚的?

这里的核心枢纽,是一个叫做 XID(事务 ID) 的东西。

1. 两阶段提交的完整执行流程

一个事务的提交,被严格拆分成了三个步骤:

  1. 阶段一(Prepare):InnoDB 引擎将数据写入 redo log,并将状态标记为 prepare(预提交)。此时,日志中会记录下该事务的全局唯一标识 XID
  2. 阶段二(Write Binlog):Server 层将变更逻辑写入 binlog。binlog 中同样会记录这个 XID
  3. 阶段三(Commit):InnoDB 引擎修改 redo log 的状态,将 prepare 变更为 commit(真正提交)。

2. 崩溃重启后的恢复逻辑

当 MySQL 异常宕机并重启时,会去扫描 redo log,并执行以下严格的判定规则:

  • 情况 1:redo log 已经是 commit 状态。
    • 说明事务已经完美走完所有流程,直接提交,恢复数据。
  • 情况 2:redo log 只有 prepare 状态,没有 commit。(最关键的边界情况)
    • 这说明系统在“写完 redo”和“最终 commit”之间崩溃了。此时,MySQL 会去磁盘提取这个 redo log 里的 XID,去 binlog 文件里寻找。
    • 分支 A:如果在 binlog 里找到了对应的 XID。说明 binlog 已经成功落盘,只是最后一步没来得及改状态。为了保证主从一致,MySQL 选择提交该事务
    • 分支 B:如果在 binlog 里没找到对应的 XID。说明 binlog 都还没写完就崩了,从库也不可能收到这条变更。为了保证主从一致,MySQL 选择回滚该事务

小结

MySQL 的日志架构是极其精妙的工程设计:

  • Redo log 用循环写保证了本机的 Crash-safe;
  • Binlog 用追加写保证了集群的主从同步与时空回溯;
  • 两阶段提交XID 则作为坚固的桥梁,完美弥合了底层引擎与上层服务之间的缝隙,保证了整个数据库生态的绝对一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值