由X/Open组织定义了分布式事务的模型,目的是允许多个资源(如数据库,应用服务器,消息队列,等等)在同一事务中访问,这样可以使ACID属性跨越应用程序而保持有效,定义了如下几个角色:
简称 | 角色 | 含义 |
---|---|---|
AP | Application,应用程序 | 说白了就是我们的系统 |
TM | Transaction Manager,事务管理器 | 就是一个在系统里嵌入的一个专门管理横跨多个数据库的事务的一个组件 |
RM | Resource Manager,资源管理器 | 数据库(比如MySQL) |
CRM | Communication Resource Manager,通信资源管理器 | 可以是消息中间件(但是也可以不用这个东西) |
补充:XA仅仅是个规范,具体的实现是数据库产商来提供的,比如说MySQL就会提供XA规范的接口函数和类库实现。
3.2 两阶段提交(2PC)
3.2.1 流程
准备阶段(prepare): 协调者向参与者发起执行事务预处理请求,参与者返回ack是否成功,就是执行sql不提交;
提交阶段(commit或rollback): 协调者收到所有ack后如果都成功则发起commit操作,有失败则rollback;
3.2.2 缺陷
1. 同步阻塞: 从阶段一执行prepare操作到阶段二执行commit之前资源都处于同步阻塞状态;
2. 单点故障: 一旦协调者节点挂掉,会导致参与者收不到通知,从而导致参与者节点始终处于事务无法完成的中间状态,即使有双机热备,如果在TM挂掉的同时接收到commit的某个库也挂了,新选举的协调者不知道哪个库接收过commit消息,无法通知提交还是回滚;
3. 数据不一致: 发送commit时只有部分参与者接收到,其他本地事务无法提交,造成数据不一致;
补充思考:两阶段提交时协调者有超时机制,参与者为何不设超时机制呢?
3.3 三阶段提交(3PC)
3.3.1 流程
canCommit阶段: 事务询问操作,检查一下各参与者是否健康,是否有能力执行事务操作;
preCommit阶段: 如果阶段一有参与者响应no状态,整个分布式事务就会中断,协调者就会向所有的参与者发送“abort”请求,否则会通知参与者执行本地操作;
doCommit阶段: 收到阶段二的响应后发送成功提交或回滚的操作;
3.3.2 与2PC的区别
1 加了一步缓冲阶段,确保执行前各参与者状态稳定;
2 参与者设置了超时机制,在阶段三会自动执行commit操作,确保不会因为协调者故障导致长时间资源阻塞;
3.3.2 缺陷
3PC对2PC存在的同步阻塞和单点故障问题起到缓解作用,但不能彻底解决,而且依然可以导致数据不一致问题:阶段三通知各参与者rollback时协调者宕机,参与者通知成功的回滚,通知失败的超时后自动提交。
补充思考:3PC里参与者超时后为何默认提交而不是回滚呢?