redo log 是 InnoDB 的恢复事实,binlog 是 Server 层和复制链路的提交事实。MySQL 分层之后,一个事务提交就不再只是“写成功”这么简单,而是要让这两套事实在崩溃恢复后仍然对得上。
两阶段提交解决的正是这个边界问题:先让 InnoDB 进入 prepare 状态,再写 binlog,最后提交 InnoDB。它不负责让提交更快,而是让本地事务、复制和恢复面对同一个结果。
先把机制边界说清楚
两阶段提交解决的是 InnoDB redo 和 Server 层 binlog 的一致性问题。提交被拆成 prepare 和 commit 两个阶段:先让 InnoDB 进入可提交状态,再写 binlog,最后让 InnoDB 正式提交。崩溃恢复时通过 binlog 和 redo prepare 状态互相校验。
整体路径
上面这张图先看入口和边界:宏观上,一个事务提交时先写 redo prepare,表示 InnoDB 已经准备好提交;然后 Server 层写 binlog 并刷盘;最后 InnoDB 写 redo commit。崩溃发生在不同点位时,恢复逻辑会根据 binlog 中是否存在对应事务来决定提交还是回滚。
第二张图再看结构关系。
底层流程
底层拆解先看数据结构。「两阶段提交」至少涉及下面几类结构:
- redo prepare 记录:表示事务已经完成存储引擎层准备。
- binlog event:Server 层对外可复制、可恢复的提交事实。
- XID:关联 redo 和 binlog 中同一事务的标识。
- redo commit 记录:表示事务在 InnoDB 中最终提交。
- 崩溃恢复流程:重启时解决 prepare 事务的去留。
再看完整执行流程:
- 事务执行完成,InnoDB 写 redo prepare。
- Server 层写入 binlog event,并按策略刷盘。
- InnoDB 写 redo commit,事务对外提交成功。
- 如果崩溃发生在 prepare 后,恢复时检查 binlog 是否有对应 XID。
- binlog 存在则提交,binlog 不存在则回滚。
取舍与边界
版本差异上,MySQL 5.7 和 8.0 都依赖这条两阶段提交链路保证 redo 与 binlog 一致。8.0 在事务型数据字典、原子 DDL 和复制元数据上增强很多,但普通事务提交的核心协调关系仍然成立。
两阶段提交提高了一致性,但也把提交路径拉长了。redo 和 binlog 都可能涉及刷盘,组提交能缓解但不能消除 fsync 成本。高并发写入下,提交阶段的磁盘抖动会直接反映到业务延迟。
典型问题:用机制化例子排查
提交阶段变慢时,不一定是 SQL 执行慢,也可能是 redo 和 binlog 的刷盘成本集中在 commit。排查时要把执行阶段和提交阶段拆开看。
可以落到这些动作:
- 把事务执行耗时和提交耗时分开观察,commit 慢不一定是锁或索引问题。
- 根据 RPO 决定 sync_binlog 与 innodb_flush_log_at_trx_commit,不要盲目追求极限吞吐。
- 控制单事务大小,减少提交阶段一次性日志压力。
- 复制链路依赖 binlog,一致性参数调整前要评估主从和恢复影响。
收束:让两套事实对齐
两阶段提交不是为了让提交更快,而是让 redo 和 binlog 在崩溃后仍然能对齐。分层架构里,一致性往往不是一个模块完成的,而是靠边界协议维持的。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 MySQL」,欢迎关注公众号 「十三Tech」。后续会继续按机制、图解和实战排查这条线更新。

