分布式事务的难点:
如果补偿事务失败,又该如何考虑?
那就得进行重试,如果还不行,那可能会造成操作错误执行,一部分事务进行提交。
注:exec时,在查询修改的数据,此时要在redo, undo日志中写数据,commit时只在redo,undo写个标记,所以exec要比commit过程慢很多。
后置提交优化:改变事务执行与提交的时序,即事务先执行,最后一起提交。
什么时候会出现不一致:第一个事务提交之后,最后一个事务提交之前,如果此时服务器down掉,会可能导致数据库不一致。
第一个事务exec;
第二个事务exec;
第三个事务exec;
第一个事务commit;
第二个事务commit;
第三个事务commit;
由此可以看出,第一个事务commit之后,最后一个事务commit之前,任何一个事务执行失败,都可能导致数据不一致,但是由于exec的时间远长于commit时间(这期间可能服务器挂掉,数据库异常等),所以极大地减小了数据不一致的可能。
4. 事务发生在多个库,甚至不同实例的数据库上,该怎么做?
要求各个节点:
二阶段提交优点:尽量保证了数据的强一致,但不是 100% 一致。
二阶段提交缺点:
CanCommit:协调者向参与者发送 Commit 请求,参与者如果可以提交就返回 ack Yes ,否则返回 ack No 。过程如下图:(注:以下3幅图取自公众号:无敌码农,作者无敌码农)
PreCommit:准备阶段,协调者根据参与者在询问阶段的响应判断是否执行事务还是中断事务,如果所有参与者都返回 Yes,则执行事务。如果参与者有一个或多个参与者返回 No 或者超时,则中断事务(参与者自身拥有超时机制会在超时后,进行本地化commit从而释放资源)。参与者执行完操作之后返回 ACK 响应,同时开始等待最终指令。如下图:
DoCommit:提交阶段,协调者根据参与者在准备阶段的响应判断是否执行事务还是中断事务,如果所有参与者都返回正确的 ACK 响应,则提交事务,如果参与者有一个或多个参与者收到错误的 ACK 响应或者超时,则中断事务。如果参与者无法及时接收到来自协调者的提交或者中断事务请求时,会在等待超时之后,会继续进行事务提交。如下图:
三阶段提交的问题:在提交阶段如果发送的是中断事务请求,但是由于网络问题,导致部分参与者没有接到请求。那么参与者会在等待超时之后执行提交事务操作,这样这些由于网络问题导致提交事务的参与者的数据就与接受到中断事务请求的参与者存在数据不一致的问题。所以无论是 2PC 还是 3PC 都不能保证分布式系统中的数据 100% 一致。
本文分享自微信公众号 - 北漂的后端开发者(gh_00dd9e194635)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。