3pc :
阶段一:CanCommit
1协调者向参与者发出CanCommit ,询问是否可以提交事务,如果所有参与者都反馈yes 才能进入下一个阶段(这一个阶段时不锁表)
优点:不像2pc 第一个阶段就开始锁表,3pc的阶段一是为了先排除个别参与者不具备提交事务能力的前提下,而避免锁表。
阶段二:PreCommit
2 当协调者向所有的参与者发出 PreCommit的命令时,如果所有参与者反馈yes,就执行事务预提交,如果有一个no或者超时无法回复,就中断事务。(这个阶段锁表)
(
== 这里要注意:中断事务的动作不是一方发起,参与者和协调者都会发起中断事务!!!==
)
(
啥是预提交?, 首先我们要知道单个实例数据库他在完成一个事务时,是这个样子的:
当一个数据库接收到要启动一个事务时:他会对这次的数据库链接专门创建一个上下文环境,在这之后,并提交事务前,sql操作都会产生log日志,例如一个
insert 操作增加一个数据,他不是直接把新增数据更新到数据库的表中而是先用log 记录下,等提交后在把log记录的数据插入到数据库表中。
所以此时查询的数据范围是: 原数据表+log日志 ,而预提交就是把这些log记录的数据转入table,但是!!!这是隔离的,!对于不在此链接的上下文
环境中其他以外的sql 操作是查询不到的。!!什么时候能真正查询到呢?就是等数据库执行commit命令成功后,这就好比,一个电工师傅接完了所有电路,
但是没有合闸前,所有做的工作叫做预备工作,而合闸那一瞬间仅仅是一个简单的推闸的动作,称之为commit!!!
所以从这个比喻中我们体会到,预提交基本上做了大量的工作,而commit(提交)命令的工作量则非常简单。
)
阶段三:doCommit
3 当协调者向参与者发do Commit命令的时候 如果参与者都返回ACK 则每个参与者就会执行commit命令,如果有一个参与者返回no 则协调者将会发回滚
与2pc 比较有一点即使因为网络原因协调者与参与者断开通信, 参与者也会自动提交commit,这样防止了一直锁表的风险,但是极端情况下想想,若
协调者发送中断命令对参与者,恰巧参与者网络断了接收不到,那么这回参与者默默提交,造成的问题就是数据不一直性!!!