当前位置: 首页 > news >正文

Mysql 中的两阶段提交

MySQL 中的“两阶段提交”(Two-Phase Commit,2PC)是用于分布式事务中的一种协议,目的是保证在多个数据库节点之间操作的一致性。虽然 MySQL 自身并不是分布式数据库,但在 使用 InnoDB 引擎和 binlog 的情况下,为了保证 InnoDB 引擎的事务和 binlog 写入的一致性,MySQL 内部也使用了一个简化的“两阶段提交”机制。

📌 1. 场景:InnoDB + Binlog 的一致性

在 MySQL 中,事务提交时需要:

  • 把事务操作写入 InnoDB 的 redo log
  • 把操作写入 binlog(用于主从复制、数据恢复)

要保证这两个步骤一致,MySQL 使用了 两阶段提交协议

🧠 2. 两阶段提交的过程

✅ 第一阶段:准备阶段(Prepare Phase)

  1. InnoDB 引擎将事务的修改写入 redo log,并写入 prepare 状态(此时 redo log 并未提交)。
  2. 如果写入 redo log 成功,则继续。

✅ 第二阶段:提交阶段(Commit Phase)

  1. MySQL Server 层将事务写入 binlog。
  2. 如果写入成功:
    • 通知 InnoDB 提交 redo log(即将 redo log 状态从 prepare 改为 commit)。
  3. 如果写入 binlog 失败:
    • 则回滚事务,并让 InnoDB 回滚 redo log。

✅ 3. 为什么需要两阶段提交?

因为:

  • InnoDB 的 redo log 和 binlog 是 两个独立的系统
  • 必须保证 两者一致,否则在 crash 恢复或者主从复制时可能出现数据不一致。

举个例子,如果:

  • redo log 已经提交(物理上持久化)
  • 但 binlog 写入失败(主从复制数据就丢了)

这就会导致数据不一致。

解释

“redo log 已经提交(物理上持久化),但 binlog 写入失败”
意思是:

  • InnoDB 的事务操作已经写入了 redo log 并提交(事务在本地已经真正生效了)。
  • 但是 binlog(用于主从复制和 crash 恢复)没有成功写入磁盘或写失败。

⚠️ 会出现什么后果?

  1. 主库上事务已经生效(数据已经更新)
  2. binlog 没有记录这个操作
  3. 从库在复制时不会收到这个事务的数据
  4. ➜ 导致主库和从库的数据出现不一致❗️

⛓️ 举个简单例子:

在主库执行了这个 SQL:

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
执行过程:
  1. InnoDB 引擎生成了 redo log,并持久化(prepare + commit)
  2. 数据 已经写入磁盘并对用户可见
  3. 接下来要写 binlog
  4. 突然磁盘坏了、网络抖动、或者某些内部故障导致 binlog 写入失败
  5. MySQL 没能把这个操作记录到 binlog
🔥 结果:
  • 主库余额真的变少了(InnoDB 的数据生效)
  • 从库完全不知道这件事(因为没有 binlog 传过去)
  • ➜ 主从数据不一致,坏了!

为了避免这种情况,MySQL 使用了两阶段提交来保证:

要么 redo log 和 binlog 都写成功并提交
要么 都不提交,回滚掉

这样就能保证主库和从库保持数据一致性。

🧠 可以这样理解:

步骤redo logbinlog最终事务状态
正常提交提交
redo 成功,但 binlog 失败⚠️ 数据不一致(必须避免)
redo 失败回滚
binlog 成功,redo 未 prepare回滚

两阶段提交的目的就是防止表格中那种 “redo 成功但 binlog 失败” 的灾难情况。

⚙️ 4. 崩溃恢复时怎么处理?

  • 如果发现 redo log 是 prepare 状态,但没有 commit:
    • 说明 binlog 没写成功,回滚事务。
  • 如果 redo log 是 commit 状态
    • 说明事务已完全提交,恢复它。

📖 5. 总结一句话

MySQL 使用“两阶段提交”机制来保证 InnoDB 和 binlog 在事务提交时的 原子性和一致性,从而支持 crash-safe 和主从复制一致性。

http://www.dtcms.com/a/112406.html

相关文章:

  • HTML应用指南:利用POST请求获取三大运营商5G基站位置信息(一)
  • 2025-04-04 Unity 网络基础5——TCP分包与黏包
  • Windows 安装和使用 ElasticSearch
  • Git提交本地项目到Github
  • vue+form实现flappybird
  • 迅饶科技X2Modbus网关-GetUser信息泄露漏洞
  • Mysql 中 B 树 vs B+ 树
  • SQL Server 2022 脏读问题排查与思考
  • HTML5 vs HTML 和 CSS3 vs CSS:全面对比
  • Spring Boot 中使用 Redis:从入门到实战
  • Websoft9分享:在数字化转型中选择开源软件可能遇到的难题
  • 神经网络能不能完全拟合y=x² ???
  • WinForm真入门(7)——Button控件详解
  • 京东运维面试题及参考答案
  • k8s进阶之路:本地集群环境搭建
  • 谷歌 Gemini 2.5 Pro 免费开放
  • 24、 Python Socket编程:从协议解析到多线程实战
  • 如何完整迁移 Git 仓库 ?
  • yum list查询时部分包查找不到流程分析
  • 54.大学生心理健康管理系统(基于springboot项目)
  • 有人DTU使用MQTT协议控制Modbus协议的下位机-含数据库
  • Redis分布式锁详解
  • AWS Langfuse AI用Bedrock模型使用完全教程
  • 【万字总结】前端全方位性能优化指南(八)——Webpack 6调优、模块联邦升级、Tree Shaking突破
  • 安卓离线畅玩的多款棋类单机游戏推荐
  • 【leetcode100】动态规划Java版本
  • Debezium日常分享系列之:Debezium 3.1.0.Final发布
  • 什么是量子计算?
  • 【代码艺廊】pyside6桌面应用范例:homemade-toolset
  • 如何实现浏览器中的报表打印