Seata分布式事物(二)AT事物模式工作机制读隔离、写隔离

1、AT 模式的前提:

1、基于支持本地 ACID 事务的关系型数据库;
2、Java 应用,通过 JDBC 访问数据库;

2、整体机制是两阶段提交协议的演变:

  • 一阶段:“业务数据”和“回滚日志”在一个本地事务中提交,释放本地锁(相当于数据库行锁)和连接资源;(本地事务,就已经在数据库持久化了)

  • 二阶段:

    • 如果没有异常:提交异步化,非常快速地完成;(正常情况,那就提交了,同步一下TC Server的状态,删除回滚日志)

    • 如果有异常:回滚通过一阶段的回滚日志进行反向补偿;(通过undo_log表中rollback_info字段);

在这里插入图片描述

3、多线程模式数据一致性

3.1写隔离

  • 一阶段本地事务提交前,需要确保先拿到全局锁 (多线程时只有一个线程优先获得全局锁)。
  • 拿不到全局锁 ,不能提交本地事务。
  • 全局锁的尝试被限制在一定范围内(源码中默认尝试10次,如果10次还没拿到全局锁就放弃),超出范围将放弃,并回滚本地事务,释放本地锁。
以一个示例来说明:
  1. 两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。
  2. tx1 先开始,开启本地事务,拿到本地锁
  3. 更新操作 m = 1000 - 100 = 900。
  4. 本地事务提交前,先拿到该记录的全局锁 ,拿到后本地提交并释放本地锁(本地锁,相当于其数据库行锁,其他线程能对其他数据进行读写)。
  5. tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。
  6. 本地事务提交前,尝试拿该记录的全局锁tx1 全局提交前,该记录的全局锁一直会被 tx1 持有,tx2 需要重试等待全局锁
    在这里插入图片描述
  7. tx1 二阶段全局提交(global commit),释放全局锁。tx2 拿到全局锁提交本地事务。在这里插入图片描述
  8. 如果 tx1 的二阶段全局回滚,则 tx1需要重新获取该数据的本地锁,进行反向补偿(数据回滚)的更新操作,实现分支的回滚。
  9. 此时,如果 tx2 仍在等待该数据的全局锁,同时持有本地锁,则 tx1 的分支回滚会失败。分支的回滚会一直重试,直到 tx2 的全局锁等锁超时,放弃全局锁并回滚本地事务释放本地锁,tx1 的分支回滚最终成功。

因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的,所以不会发生 脏写 的问题。

3.2、读隔离

  • 在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted)

    • mysql 默认是可重复读(Repeatable Read:在Read Committed基础上重复读)
    • oracle,sql server 读已提交(Read Committed)
  • 如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。
    在这里插入图片描述

在这里插入图片描述

  1. SELECT FOR UPDATE 语句的执行会申请全局锁
    • for update仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效。在进行事务操作时,通过“for update”语句,MySQL会对查询结果集中每行数据都添加排他锁,其他线程对该记录的更新与删除操作都会阻塞。排他锁包含行锁、表锁。
  2. 如果全局锁被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。
  3. 这个过程中,查询是被block住的,直到全局锁拿到,即读取的相关数据是已提交的,才返回。

出于总体性能上的考虑,Seata 目前的方案并没有对所有 SELECT 语句都进行代理,仅针对 FOR UPDATE 的 SELECT 语句。

如果某个表操作做了分布式事物,那么在查询的时候需要做防止脏读的处理(SELECT FOR UPDATE),因为查询的数据可能会被回滚,引起脏读

本文内容参考官网,对官网内容进行了部分的解析

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值