与两阶段提交不同的是,三阶段提交有两个改动点:
1. 引入超时机制。同时在协调者和参与者中都引入超时机制;
2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段。
1. CanCommit 阶段
3PC 的 CanCommit 阶段其实和 2PC 的准备阶段很像。协调者向参与者发送 commit 请求,参与者如果可以提交就返回 Yes 响应,否则返回 No 响应。
(1)事务询问:协调者向参与者发送 CanCommit 请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
(2)响应反馈:参与者接到 CanCommit 请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回 Yes 响应,并进入预备状态。否则反馈 No。
2. PreCommit 阶段
协调者根据参与者的反应情况来决定是否可以继续事务的 PreCommit 操作。根据响应情况,有以下两种可能:
假如协调者从所有的参与者获得的反馈都是 Yes 响应,那么就会执行事务的预执行。
(1)发送预提交请求:协调者向参与者发送 PreCommit 请求,并进入 Prepared 阶段。
(2)事务预提交:参与者接收到 PreCommit 请求后,会执行事务操作,并将 undo 和 redo 信息记录到事务日志中。
(3)响应反馈:如果参与者成功的执行了事务操作,则返回 ACK 响应,同时开始等待最终指令。
假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
(1)发送中断请求:协调者向所有参与者发送 abort 请求。
(2)中断事务:参与者收到来自协调者的 abort 请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
3. doCommit 阶段
该阶段进行真正的事务提交,也可以分为以下两种情况。
3.1 执行提交
(1)发送提交请求:协调接收到参与者发送的 ACK 响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送 doCommit 请求。
(2)事务提交:参与者接收到 doCommit 请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
(3)响应反馈:事务提交完之后,向协调者发送 ACK 响应。
(4)完成事务:协调者接收到所有参与者的 ACK 响应之后,完成事务。
3.2 中断事务
协调者没有接收到参与者发送的 ACK 响应(可能是接受者发送的不是 ACK 响应,也可能响应超时),那么就会执行中断事务。
(1)发送中断请求:协调者向所有参与者发送 abort 请求。
(2)事务回滚:参与者接收到 abort 请求之后,利用其在阶段二记录的 undo 信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
(3)反馈结果:参与者完成事务回滚之后,向协调者发送 ACK 消息。
(4)中断事务:协调者接收到参与者反馈的 ACK 消息之后,执行事务的中断。
三阶段提交的问题:
网络分区可能会带来问题。需要四阶段解决:四阶段直接调用远程服务的数据状态,确定当前数据一致性的情况。