最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MySQL在执行Commit动作时是如何协调两阶段提交的
时间:2026-07-16 08:21:58 编辑:袖梨 来源:一聚教程网
MySQL的COMMIT是两阶段提交流程:先prepare(redo log刷盘并标记PREPARE+XID),再由binlog写入成功后触发commit(redo log更新为COMMIT),崩溃恢复时通过XID比对redo log与binlog一致性来决定提交或回滚。
MySQL 的 COMMIT 不是原子操作,而是由 InnoDB 和 Server 层协同完成的两阶段流程;你看到的“提交成功”,其实是协调者(InnoDB 事务管理模块)确认 redo log 和 binlog 都已按序落盘后的结果。
prepare 阶段:先让 redo log 进入可恢复状态
执行 COMMIT 后,InnoDB 立即进入 prepare 阶段:
-
redo log写入缓冲区,并调用fsync刷盘(受innodb_flush_log_at_trx_commit=1控制),状态标记为PREPARE,同时写入事务唯一标识XID; - 此时数据尚未对外可见,锁未释放,
undo log也未清理; - 关键点:如果此刻崩溃,InnoDB 重启后会扫描
redo log,发现PREPARE状态事务,但不会直接提交——它要等binlog的“判决”。
commit 阶段:binlog 成为最终裁决者
Server 层收到 InnoDB 的 prepare 成功反馈后,才开始写 binlog:
-
binlog追加写入文件,并调用fsync(受sync_binlog=1控制),且必须关联同一XID; - 若
binlog写失败(如磁盘满、权限错误),Server 层通知 InnoDB 执行rollback,该事务彻底作废; - 若
binlog写成功,Server 层向 InnoDB 发送commit指令,InnoDB 将redo log中对应XID的记录状态更新为COMMIT(这步不强制刷盘,只需 write 到 OS page cache); - 随后释放锁、清理
undo log、事务真正结束。
崩溃恢复时,MySQL 怎么“读心”?
MySQL 重启时并不“猜测”,而是严格比对两个日志中的 XID:
- 如果
redo log里有XID标记为PREPARE,但binlog里查不到该XID→ 认定binlog写失败,自动回滚; - 如果
binlog里有该XID,但redo log中无对应PREPARE记录 → 理论上不应发生(因为binlog写入前必须过 prepare),若出现,说明流程被绕过(如禁用了innodb_support_xa),将导致主从不一致; - 只有两者都存在且匹配,才完成最终提交 —— 这就是为什么
binlog在恢复中充当“裁判”角色。
容易被忽略的配置陷阱
两阶段提交能否生效,高度依赖两个参数的实际值:
-
innodb_flush_log_at_trx_commit=0/2:prepare 阶段的redo log可能未刷盘,崩溃后连PREPARE状态都丢失,binlog却已存在 → 主从不一致; -
sync_binlog=0:binlog仅写入文件系统缓存,崩溃后丢失,InnoDB 会因找不到XID而回滚,但业务可能已收到“提交成功”响应; -
innodb_support_xa=OFF(MySQL 5.7.7+ 默认 ON):禁用 XA 协议支持,会跳过 prepare 阶段,退化为单阶段提交,完全破坏 2PC 机制。
真正起作用的不是 COMMIT 这个语句本身,而是背后那套靠 XID 对齐、靠 fsync 顺序和靠崩溃后交叉校验维持的协作逻辑。一旦任一环节脱离这个链条,一致性就不再有保障。
相关文章
- 王者荣耀世界零氪玩家如何生存 07-28
- 快手极速版怎么绑定手机号 07-28
- 明日方舟和轻松小熊联动活动内容一览 07-28
- 逆战未来黎明之光 逆战未来黎明之光玩法机制与新手入门指南 07-28
- 植物大战僵尸融合版毁灭土豆地雷介绍 07-28
- 逆战未来飓风之龙 逆战未来飓风之龙武器获取方法详解 07-28