🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 简介 两阶段提交(2PC),在客户端和多个数据库之间增加了一个事务协调者,同时**将事务的提交分为准备和提交两个阶段** # 准备阶段 事务协调者给每个数据库发送prepare消息,**每个数据库要在本地执行事务,写本地的redo和undo日志,但不提交日志** 大致流程如下: 1. 事务协调者节点向所有数据库询问是否可以执行提交操作,并开始等待各参与者节点的响应 2. 数据库节点执行询问发起为止所有事务操作,并将undo信息和redo信息写入日志 3. 数据库节点响应事务协调者节点发起的询问.如果数据库节点的事务操作实际执行成功,则返回一个'同意'消息.如果执行失败,则返回一个'中止'消息 # 提交阶段 如果事务协调者收到了数据库的中止消息或等待超时,则直接发给每个数据库发送rollback消息,要求回滚操作. 如果事务协调者收到了数据库的同意消息,则发送commit消息,要求进行提交操作. 执行完毕之后释放所有事务处理过程中使用的资源 大致流程如下 1. 事务协调者节点向所有数据库发起commit/rollback请求,并开始等待各参与者节点的响应 2. 数据节点执行commit/rollback动作并释放事务占用的资源,之后向事务协调者发送完成消息 3. 事务协调者收到所有数据库的反馈消息后完成或取消事务 # 问题 两阶段提交看似解决了分布式数据一致性的问题,其实这个设计存在一些明星的问题: 1. 阻塞执行,速度慢 : 从刚才描述可以看出,协调者和数据库的一系列提交或回滚动作都是阻塞执行的,这必然导致整个分布式事务运行效率缓慢 2. 单点问题 : 两阶段提交的核心枢纽是事务协调者节点,如果这个节点失效了,那么整个事务机制也就瘫痪了.同时由于协调者失效,会导致数据库的资源一直占有无法释放 3. 数据不一致 : 试想一下,在提交阶段,当事务协调者向所有数据发送commit请求之后,由于网络问题只有一部分数据库收到了请求消息并执行了commit消息,而另一部分数据库没有收到commit消息,多个数据库之间就会产生数据不一致的问题