解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言
在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC)通过增加预提交阶段和超时机制,旨在解决2PC的阻塞风险。值得注意的是,MySQL数据库的Binlog与InnoDB引擎通过内部两阶段提交机制,实现了事务日志与存储引擎状态的一致性保障。
两阶段提交
第一阶段:准备阶段,第二阶段:提交阶段。将提议的节点称为协调者(coordinator),其他参与决议节点称为参与者。
第一阶段:协调者发起一个提议,分别问询各参与者是否接受,参与者如果认为自己可以提交事务,它们将执行所有必要的操作但不提交(记录redo log,undo log),正常执行返回Yes,否则返回No。
第二阶段:协调者根据参与者的反馈,提交或回滚事务,如果参与者全部同意则提交,只要有一个参与者不同意就回滚。
MySQL的两阶段提交
当在 InnoDB 中执行事务,并且启用了 Binlog 时,提交事务时会触发两阶段提交过程。
- 当有数据需要更新的时候,InnoDB 引擎就会先把记录写到redo log buffer以及binlog cache(线程独有的),并更新内存(chang buffer),这个时候更新就算完成了。
-
- 如果是唯一索引更新操作会写入到redo log,普通索引的更新操作会先写入到change buffer,在合适的时机merge到redo log。
- 事务提交时写入 redo log 并变成 prepare 状态。(一阶段)
- 再把 binlog cache 写到 binlog 文件中,最后 redo log 变成 commit 状态。(二阶段)
三阶段提交
三阶段提交,是二阶段提交(2PC)的改进版本。与两阶段提交不同的是,三阶段提交有两个改动点。
- 引入超时机制。同时在协调者和参与者中都引入超时机制。
- 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
第一阶段CanCommit:事务协调者向所有参与者发送询问消息(CanCommit),询问它们是否能够提交事务。
第二阶段PreCommit:协调者根据参与者的反应情况来决定是否可以进行事务的PreCommit操作。
- 参与者如果认为自己可以提交事务,它们将执行所有必要的操作但不提交(记录redo log,undo log),并锁定资源,然后向协调者发送准备提交(PreCommit)的响应。
- 协调者等待来自所有参与者的响应。如果收到所有参与者的肯定回复,它将进入提交阶段;如果任何一个参与者否定或者等待超时,它将进入中止阶段。
第三阶段DoCommit:
- 如果进入提交阶段,协调者向所有参与者发送提交消息(doCommit),指示它们正式提交事务。
- 如果进入中止阶段,协调者向所有参与者发送中止消息(abort),指示它们回滚事务。
两阶段提交和三阶段提交区别?
阻塞性问题
两阶段提交会存在阻塞性问题,如果参与者都已经执行一阶段,但协调者崩溃的话,参与者会进入等待状态,直到协调者恢复并做出决定。
三阶段提交利用超时机制解决阻塞性问题,参与者在预提交阶段后等待协调者的最终提交请求时,如果超过超时时间可以选择回滚事务。
感谢您的阅读!如果文章中有任何问题或不足之处,欢迎及时指出,您的反馈将帮助我不断改进与完善。期待与您共同探讨技术,共同进步!