news 2026/4/18 11:22:28

“我这显示转账成功了你没收到钱?“--MySQL Redo Log和binlog两阶段提交到底在防什么?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
“我这显示转账成功了你没收到钱?“--MySQL Redo Log和binlog两阶段提交到底在防什么?

凌晨三点,你刚上线一个支付功能。

用户 A 给 B 转了 100 块,页面显示“转账成功”。

可第二天一早,客服炸了——B 的账户没收到钱!

更诡异的是,主库数据是对的,但从库却少了这笔记录。

你懵了:“明明 COMMIT 成功了,怎么还会丢数据?”

如果此时主库故障,高可用进行了切换,此刻你是不是更崩溃?

今天,我们就用一次真实转账,探索一下MySQL里的Redo Log、Binlog以及所谓的两阶段提交(2PC)--这套被无数大厂面试官反复追问、却少有人真正清楚理解的底层逻辑。

1. 你以为的“提交”,其实只是开始

当你执行:

BEGIN;UPDATE accounts SET balance = balance - 100 WHERE user = 'A';UPDATE accounts SET balance = balance + 100 WHERE user = 'B';COMMIT;

你以为 COMMIT 一敲,钱就稳了?

错!!! 此时数据可能还在内存里(Buffer Pool),根本没写到磁盘。如果服务器突然断电,这笔交易就会凭空消失。

那 MySQL 怎么保证“不丢”?靠 Redo Log。

Redo Log 是 InnoDB 的“后悔药”:它先把你改的数据“记一笔账”,哪怕机器炸了,重启后也能照着日志把数据补回来。

但问题来了:光有 Redo Log,从库怎么办?

这时候,Binlog 登场了。Binlog 是 MySQL Server 的“操作录像”:它记录你执行了什么 SQL(或具体哪行变了),专门给从库看,也用于备份恢复。

于是,一个事务要同时写两个日志:

  • InnoDB 写 Redo Log(保自己)

  • Server 写 Binlog(保别人)

但这两个模块互不隶属,谁先写?谁后写?万一中间崩了怎么办? 这就是灾难的起点。

2. 最危险的“半提交”时刻

想象这个场景:

Redo Log 写成功了(事务在主库已“生效”);

正要写 Binlog,机房跳闸或者服务器故障了!

结果:

主库重启后,这笔转账还在;

但从库压根没收到 Binlog,余额没变。

主从不一致!用户投诉、对账失败、资金差错……

反过来也一样:

Binlog 写进去了,但从库还没拉;

Redo Log 没落盘就崩了 → 主库回滚,但从库执行了 → 凭空多出 100 块!

这两种情况,在金融系统里都是致命事故。

所以,MySQL 必须确保:Redo Log 和 Binlog 要么都成功,要么都失败。

怎么做到?答案就是 —— 两阶段提交(Two-Phase Commit, 2PC)。

3. 两阶段提交:用“准备”锁住不确定性

2PC的核心思想很简单:把提交拆成两步,中间加个“准备”状态,并用事务 ID(XID)把两个日志拴在一起。

如果是默认双1(innodb_flush_log_at_trx_commit、sync_binlog参数都为1,后文也用"双1模式"代指)模式的话,正常流程简化后(写内存等忽略)的长这样:

阶段

步骤

执行者

操作

日志状态

是否

刷盘

作用

执行阶段

1

InnoDB + Server

执行 DML,修改 Buffer Pool;生成 Redo Log(内存)和 Binlog(内存)

Redo: in-memory
Binlog: in-buffer

数据变更暂存内存

Prepare 阶段

2

InnoDB

将 Redo Log 标记为PREPARE,写入 XID=1001

Redo: PREPARE(XID=1001)

是(fsync)

锁定事务状态,防止回滚

Commit 阶段 - Step 1

3

Server

将事务的 Binlog 写入 binlog 文件

Binlog: contains XID=1001

是(fsync)

确保从库能同步

Commit 阶段 - Step 2

4

InnoDB

在redo log中添加commit记录(含xid)

Redo: COMMIT(XID=1001)

是(fsync)

完成事务提交

完成

5

返回客户端“事务提交成功”

对外可见

其中每一步的关键动作如下

步骤

操作

关键动作

1

执行 UPDATE

数据改在内存,Redo 和 Binlog 先缓存

2

Prepare 阶段

InnoDB把Redo Log标为PREPARE, 刷盘

3

写 Binlog

Server 把 Binlog 写入文件,刷盘

4

Commit 阶段

InnoDB在Redo Log里追加commit,刷盘

✅ 只有走完这四步,MySQL才敢告诉客户端:“事务成功”。

注意第 2 步和第 3 步之间的“缝隙”——这是唯一可能出问题的地方。

但正因为有了 PREPARE 状态 + XID,MySQL 才能在崩溃后“断案”。

流程图如下

4. 崩溃恢复:靠 Binlog 当“裁判”

MySQL 启动时,InnoDB 会自动扫描 Redo Log,重点盯住那些卡在 PREPARE 的事务。然后,它做一件事:拿着事务的 XID,去 Binlog 里查有没有这条记录。

Redo Log 状态

Binlog 中是否存在相同 XID?

恢复动作

原因

PREPARE

✅ 存在

提交(Commit)

Binlog 已落盘,说明事务已进入 Commit 阶段,应完成提交

PREPARE

❌ 不存在

回滚(Rollback)

Binlog 未写入,说明事务未完成 2PC,应视为未提交

COMMIT

一定存在(否则是bug)

已提交,无需处理

Redo Log 已完整提交

无记录

无需对比

无此事务

事务未开始或已清理

举个例子:

  • 在Prepare阶段后断电(Redo prepare 成功,Binlog 没写)→ Binlog 查无此 XID → 回滚 → A 和 B 钱都没动 →因为没有binlog,从库也不会有变化,主从一致。

  • 在写Binlog后断电(Binlog 已写,Redo commit没写→Binlog 有记录→提交→转账成功→有binlog,从库也更新成功→主库崩溃恢复后主库操作也成功→ 主从一致。

这就是 2PC 的精妙之处:用Binlog里的状况作为最终裁决者,兜底所有不确定性。

5. 对比:Redo Log vs Binlog

下面从多个维度来对比一下

维度

Redo Log

Binlog

所属层级

InnoDB 存储引擎层

MySQL Server 层

日志类型

物理日志(记录“页如何变”)

逻辑日志(记录“SQL 或行如何变”)

记录内容示例

“page 123, offset 456: 900 → 800”

UPDATE accounts SET balance=800 WHERE id=1;

(STATEMENT)
或记录前后镜像(ROW)

主要用途

崩溃恢复(Crash Recovery)

主从复制(Replication)、时间点恢复(PITR)

写入时机

事务执行过程中生成,提交时刷盘

事务提交前生成,提交时写入并可刷盘

存储方式

固定大小的循环文件(默认 48MB,可配置)

追加写入的多个文件(按max_binlog_size切割)

是否支持事务

是(与事务强绑定)

是(但需配合 InnoDB 才能保证 ACID)

是否跨引擎

否(仅 InnoDB 使用)

是(所有引擎都可写,但 MyISAM 不支持事务)

刷盘控制参数innodb_flush_log_at_trx_commit

• 1:每次 COMMIT 刷盘(安全)
• 0/2:延迟刷盘(性能好,可能丢数据)

sync_binlog

• 1:每次事务刷盘(安全)
• N:每 N 次事务刷一次(性能好,最多丢 N-1 个事务)

是否可关闭

可关闭(但强烈不建议,会失去崩溃恢复能力)

可关闭(但关闭后无法做主从复制或 PITR)

恢复速度

极快(直接重做物理页)

较慢(需解析 SQL 或逐行应用)

💡Tips:

  • Redo Log 是 InnoDB 的“内部保险”,Binlog 是 MySQL 的“对外凭证”。两者必须协同,才能既保内(恢复)又保外(复制)

  • 生产环境,这两个参数必须设为1,否则,你所谓的“高可用”,可能只是造成数据不一致的“高风险”项

6. 常见配置组合与风险分析

innodb_flush_log_at_trx_commitsync_binlog

安全性

性能

最大可能丢失数据

适用场景

1

1

最高

0 事务(操作系统崩溃也不丢失)

金融、支付等强一致性场景

1

1000

最多999个已提交事的Binlog

高吞吐、容忍短暂主从延迟

2

1

操作系统崩溃时可能丢最近1秒 Redo

一般业务,追求性能及安全性平衡

0

0

最高

最多1秒内的所有事务

日志型、非关键数据

⚠️ 注意:只要 sync_binlog > 1,就存在主从不一致风险,因为 Binlog 可能未落盘而 Redo Log已提交

7. 高频问题

简单整理几个关于redo log和binlog的高频面试题及回答要点

问题

核心要点

回答关键词

Redo Log和Binlog有什么区别

层级、内容、用途、刷盘机制

物理 vs 逻辑、InnoDB vs Server、崩溃恢复 vs 主从复制

为什么需要两阶段提交

防止 Redo 与 Binlog 状态不一致

原子性、XID 关联、主从一致

2PC 流程是怎样的

Prepare→Binlog→commit

核心三步、XID、刷盘顺序

崩溃后如何恢复

查 Redo 中 PREPARE 事务,核对 Binlog

XID 匹配、提交/回滚决策

能否只用 Redo Log

可以恢复,但无法复制

缺少Binlog→无法主从同步

组提交是什么

优化 2PC 的刷盘性能

多个事务合并fsync,提升吞吐


之前我们整理过其他的日志(slow log、general log、错误日志),对于历史文章链接如下:

MySQL源码学习系列(二)--面试高频问题:general log、slowlog记录顺序

MySQL错误日志文件突然暴涨的原因

慢SQL探秘之为什么我的SQL很慢却没记录在慢查询日志里

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 3:34:59

Potrace完全指南:从位图到矢量图的终极转换方案

Potrace完全指南:从位图到矢量图的终极转换方案 【免费下载链接】potrace [mirror] Tool for tracing a bitmap, which means, transforming a bitmap into a smooth, scalable image 项目地址: https://gitcode.com/gh_mirrors/pot/potrace 想要将像素化的位…

作者头像 李华
网站建设 2026/4/18 3:29:03

Open-AutoGLM官方邀请码发放内幕(稀缺资源,手慢无)

第一章:Open-AutoGLM官方邀请码发放内幕Open-AutoGLM 作为新一代开源自动代码生成框架,自项目启动以来便受到开发者社区的高度关注。其封闭测试阶段采用邀请码机制控制访问权限,确保系统稳定性与用户体验。官方邀请码的发放并非随机行为&…

作者头像 李华
网站建设 2026/4/18 10:08:21

GPT-SoVITS在语音邮件自动回复中的应用场景

GPT-SoVITS在语音邮件自动回复中的应用场景 在企业通信日益智能化的今天,一条冰冷的“您好,我现在无法接听电话”早已无法满足用户对服务体验的期待。越来越多的企业开始寻求更自然、更具亲和力的语音交互方式——尤其是当高管、医生或客服代表无法实时响…

作者头像 李华
网站建设 2026/4/18 3:35:43

5个关键要素确保YashanDB数据库的成功实施

在当前的数据库技术领域,企业面临的挑战主要集中在性能瓶颈、数据一致性、扩展性和高可用性等多方面。由于数据的迅速增长和应用需求的多样化,企业亟需高效而稳定的数据库解决方案。YashanDB作为一款具备分布式、共享集群等架构的数据库管理系统&#xf…

作者头像 李华