前言
简单了解下什么是事务?用户定义的一系列数据库操作,这些操作可以视为一个完整的逻辑处理单元,要么全部执行,要么全部不执行。为保障事务是正确可靠的,事务具备4个特性:
原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成。
一致性(Consistency):在事务开始之前和事务结束之后,数据的完整性没有被破坏,比如;A和B共有200,A向B转账不管成功还是失败,总额还是200。
隔离性(Isolation):防止多个事务并发执行时导致数据不一致。
持久性(Durability):事务处理完成后对数据的修改是永久的。
通常一致性和隔离性通过锁实现,原子性和持久性通过日志实现。
那什么是分布式事务?用户定义的一系列数据库操作,事务涉及到多个数据库或者多个服务,这个时候事务就不像本地事务一样好控制了,于是有了分布式事务解决方案,目的是为了保障分布式系统中数据一致性。
文章中出现的'事务协调者'字眼,什么是事务协调者?本地事务通过数据库可以直接begin ... rollback ... commit执行操作,那跨数据如何处理?这个时候需要一个中间人来通知数据库是否提交或者回滚,这个中间人可以叫做事务协调者。
XA规范
定义事务协调者和数据库之间的规范,事务协调者用它来通知数据库事务的开始、结束、提交、回滚等。XA规范由数据库厂商提供存在三种角色,彼此之间都有交互。
AP:Applicatioin 应用程序
TM:Transaction Manager事务管理者
RM:Resource Manager资源管理者(DB)
2PC 两阶段提交
事务协调者在第一段发送预备提交,如果各参与者响应yes后在第二段发送执行提交,各参与者提交事务并释放连接;如果各参与者响应no或者协调者在规定时间内未收到响应,第二段发送回滚操作,各参与者回滚并释放连接。
缺点:
单点故障:协调者出错,事务失败。
阻塞资源:两阶段内保持连接,占用数据库连接,性能低。解决:1阶段直接提交断开连接,二阶段记录提交前的状态,失败直接回归到之前状态(seata解决)。
数据不一致:二阶段提交过程中有一方RM出错,导致数据不一致。解决:用脚本检查数据,如果出现异常,修改数据达到一致。
3PC 三阶段提交
3PC优化了2PC一处缺点,第一段会检查是否可以成功操作,避免因操作失败而占用资源,参与者响应yes后再继续后续操作,后续操作则与2PC一致。
can commit:询问能否操作
pre commit:预备提交
do commit:执行提交
TCC解决方案
TCC分为三个阶段:
try:对资源进行锁定或者预留。
confirm:如果Try阶段都响应正常,执行Try阶段预留资源操作。
cancel:如果Try阶段响应异常,撤销Try阶段预留资源操作。
在进行一系列操作时,都有与其对应的确认和撤销操作。上图理解:
最大努力通知方案
简单理解:在一个大的事务分成多个小事务的情况下,某一个事务执行成功后通知另一事务,如果通知不到,在规定的次数一直通知,同时另一个事务可以去该事务主动拉取数据。
补充
最近在看阿里开源的seata,发现文档中有特别详细的关于分布式事务的介绍seata官方文档