针对两阶段提交存在的问题,三阶段提交协议通过引入一个 预询盘 阶段,以及超时策略来减少整个集群的阻塞时间,提升系统性能?
为啥加一个流程就能减少阻塞时间,接着往下看
针对2PC存在的问题 3PC 做了如下改变
- 引入超时机制。同时在 TM 和 RM 中都引入超时机制。
- 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
超时机制:
-
对于 TM 来说如果在指定时间内没有收到所有 RM 的应答,则可以自动退出
WAIT
状态,并向所有参与者发送rollback
通知。 -
对于 RM 来说如果位于 READY 状态,但是在指定时间内没有收到TM的第二阶段通知,则不能武断地执行 rollback 操作,因为TM 可能发送的是 commit 通知,这个时候执行 rollback 就会导致数据不一致。
互询机制,让 RM A 去询问其他 RM B 的执行情况。
- 如果 B 执行了 rollback 或 commit 操作,则 A 可以大胆的与 B 执行相同的操作;
- 如果 B 此时还没有到达 READY 状态,则可以推断出 TM 发出的肯定是 rollback 通知;
- 如果 B 同样位于 READY 状态,则 A 可以继续询问另外的参与者。
- 只有当所有的 RM 都位于 READY 状态时,此时两阶段提交协议无法处理,将陷入长时间的阻塞状态(TM 可能崩溃了)
3PC把2PC的准备阶段再次一分为二:预询盘(can_commit)、预提交(pre_commit)以及事务提交(do_commit)
流程
第一阶段 预询盘

- TM 向各 RM 发送
CanCommit
的请求,询问是否可以执行事务提交操作,并开始等待各 RM 的响应 - RM 收到
CanCommit
请求后,正常情况下,如果自身认为可以顺利执行事务,那么会反馈 Yes 响应,并进入预备状态,否则反馈 No
异常情况:
- 部分 RM 收到
canCommit
指令后,直接反馈不能开始事务,TM 向所有参与者发送 abort 请求。 - TM 等待反馈超时,向所有 RM 发送 abort 请求。
- RM 预检没问题,但一直无法接收到下一步的的指令(反馈
can commit
超时 或接收RM 的下一步指令超时),自省中断事务的中断 - RM 收到来自 TM 的
abort
请求之后执行事务中断
第二阶段 预提交
这个阶段类似2PC 的第一阶段,这个环节根据阶段 1 的参与者的反馈不同,而执行不同的逻辑:
1)如果任意一个 RM 在阶段 1 向 TM 反馈了 No 响应,或者 TM 等待 RM 反馈超时,那么就会中断事务,中断执行逻辑如下:
- TM 向所有 RM 发送 abort 请求
- RM 无论是收到来自 TM 的 abort 请求,还是等待超时,都执行事务中断
2)另一种情况,如果 TM 接收到各RM 反馈都是 Yes,那么才执行事务预提交,执行逻辑如下:
- TM 向各RM 发送
preCommit
请求,并进入prepared
阶段 - 各 RM 接收到
preCommit
请求后执行事务操作,并将 Undo 和 Redo 信息记录到事务日记中,但事务不提交 - 如果各 RM 都成功执行了事务操作,那么反馈给TM Ack 响应,同时等待最终指令,提交
commit
或者终止abort
第三阶段 事务提交
这个阶段类似 2PC 的第二个阶段,这个环节根据阶段2 RM 不同反馈,而执行不同的逻辑:
1)假设 TM 正常工作,并且有任意一个 RM 在阶段 2 反馈 No,或者在等待RM 的反馈超时后,都会主动中断事务
- TM 向所有RM 节点发送 abort 请求
- RM 接收到 abort 请求后,利用 undo 日志执行事务回滚,并在完成事务回滚后释放占用的资源后,向 TM 发送 ack 信息,反馈事务回滚结果
- TM 接收到所有 RM 反馈的 ACK 消息之后,完成事务的中断
2)假设 TM 正常工作,接收到了所有 RM 的 ack 响应,那么它将从预提交阶段进入提交状态
- TM 向所有 RM 发送
doCommit
请求 - RM 收到
doCommit
请求后,正式提交事务,并在完成事务提交后释放占用的资源,向 TM 发送 ACK 信息,反馈事务提交结果 - TM 接收到所有参与者 ack 信息,整个事务完成
异常情况:
- RM 收到
PreCommit
指令并正常执行事务,给 TM 反馈preCommit
完成后,如果未能等到下一步的doCommit
指令超时了,会自主提交事务。因为询问阶段是一致通过的,执行到这个阶段整个事务成功的概率已经很高了 - 部分 RM 执行
preCommit
异常,部分参与者执行preCommit
正常,但此时 TM 挂了,那么通过 RM 的超时自醒机制,就出现部分参与者提交,部分参与者回滚,出现数据不一致。 - TM 发送了 abort 指令,RM 超时未收到指令就提交了事务,其他 RM 收到了协调者发送的 abort 指令后执行了回滚,也会出现数据不一致。
Keidar 和 Dolev (1998) 建议使用增强型三阶段提交 (E3PC) 协议来消除此问题。E3PC 协议需要至少三个往返才能完成,这将有很长的延迟才能完成每笔交易。
总结
- 相较于2PC,3PC引入超时机制与质询机制,增加了额外的通信开销,增加了系统网络负载与延迟
- 异常情况仍然无法避免数据不一致的情况
- 依赖于时间同步,3PC的正确执行依赖于系统中所有 RM 和 TM 的时间同步。如果时间同步不准确,可能导致超时机制失效或误判,影响事务的最终一致性。