LXX的网络日志
人因梦想而伟大
笔记-针对2PC的问题引入3PC分布式事务方案

3PC协议

3PC主要是为了解决2PC协议的一些问题。

3PC的话改成了下面的过程:

(1)CanCommit阶段:TM发送一个CanCommit消息给各个数据库,然后各个库返回个结果,需要注意的是,这里不会执行实际的SQL语句的,说白了,就是各个库看看自己网络环境是否OK.

(2)PreCommit阶段:如果各个库对CanCommit消息返回的都是成功,那么就进入PreCommit阶段,TM发送PreCommit消息给各个库,这个时候相当于2PC里面的阶段一,其实就会执行各个SQL语句,只是没有提交。如果有个库的CanCommit消息返回失败了,TM就会发送abort消息给各个库,结束这个事务。

(3)DoCommit阶段:如果各个库的PreCommit阶段都返回了成功,那么发送DoCommit消息给各个库,去提交事务,如果各个库都返回提交成功给TM,那么分布式事务成功。如果有个库的PreCommit返回失败,或者一直没返回超时了,那么TM认为分布式事务失败,直接发送abort消息给各个库,进行回滚。各个库回滚成功之后通知TM,进行分布式事务回滚。

跟2PC相比,主要做了下面两个点的改进:

(1)引入了CanCommit阶段

(2)在DoCommit阶段,各个库自己也有超时机制,也就是说,如果一个库收到了PreCommit自己返回成功了,等了一会,如果超时时间到了,还没有收到TM发送DoCommit消息或者abort消息,直接判定为TM可能出故障了。这个时候直接自己执行commit操作,去提交事务。

为什么一个库接收到PreCommit消息呢?因为第一个阶段各个库对CanCommit一定都返回成功了,说明各个库的基本环境都OK,可以运转,没有一个库挂掉的。所以TM才会发送PreCommit消息给各个库。

3PC的缺陷

在2PC阶段,如果TM挂了或者数据库出现网络故障,无法接收commit消息,此时会导致数据库一直锁住资源,别人要访问这个资源就会一直被阻塞。

在3PC里面倒是不会这样,在DoCommit阶段,TM挂了数据库会自动提交。

但是,它还是有缺陷,TM在DoCommit阶段发送了abort消息给各个库,结果某个库因为脑裂问题,没有收到abort消息,那个库自己却执行了commit操作,还是会导致数据不一致的问题。

无论是2PC还是3PC都无法完全保证分布式事务是完全OK的,在某些情况还是会出问题。