二阶段提交
在分布式系统中,每个节点都可以知道自己事务的提交是否成功,但是却不知道其他节点的事务情况,于是就有了多种分布式实现方式来解决分布式事务的问题。
二阶段提交(Two-phase Commit),可以说是一致性协议或者原子协议,保证分布式系统数据的一致性。
主要的角色有协调者和参与者。协调者先通知参与者操作是否成败,得到反馈后,再通知参与者提交或者中止操作。
二阶段提交顾名思义就是有两个阶段,一个是提交请求阶段,也叫投票阶段,另一个是提交阶段。
提交请求阶段
- 事务发起方发起请求调用给协调者
- 协调者向所有参与者节点发起是否可以执行提交操作请求,然后等到所有节点的响应
- 参与者执行所有的事务准备,并将Undo信息和Redo信息写入日志
- 如果参与者所有的事务都执行成功,返回同意,否则,返回中止
简单的说,就是协调者对所有参与者说,你们行不行,参与者检查一下自身条件对协调者回复,行或不行。
提交阶段
提交阶段,根据参与者反馈的结果,协调者会有两种处理方式。如果所有参与者都返回同意,则到提交阶段,如果有部分参与者返回中止,或者在超时时间内协调组没收到参与者的反馈,则到中断阶段。
提交
- 协调者向所有参与者发送提交请求
- 参与者提交事务,并释放事务期间占的资源
- 参与者向协调者发送ack消息
- 协调者收到所有ack消息后,协调者向事务方反馈完成事务信息
中断
- 协调者向所有参与者发送回滚请求
- 参与者通过Undo回滚,并释放事务期间占的资源
- 参与者向协调者发送ack消息
- 协调者向事务方反馈事务失败信息
缺点
- 阻塞:执行过程中间,节点都处于阻塞状态,等待这其他节点操作成功或失败,数据库资源得不到释放
- 单点问题:如果协调者挂掉,那直接影响整个事务的提交。特别是在过程中挂掉,其他参与者就陷入了阻塞
- 数据一致性:在第二个阶段中,如果某些参与者因为网络抖动,没收到提交请求,而其他参与者已经提交了事务,则数据会不一致
mysql对XA的支持
# 开启事务
mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
# 结束事务
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
# 提交请求
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
# 提交
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。