seata
AT模式
设计
全局锁:业务层面
本地锁:数据库层面
全局锁:模块id:表id:记录id
写隔离
tx1 业务A 获取本地锁,修改,获取全局锁,提交,。。。tx1 全局结束,释放全局锁
tx2 业务A 获取本地锁,修改,获取全局锁失败,重试,重试,超时。。。
。。。。。。。。。。。。。。。。。。。。。。。。 ,重试成功,提交。。。。
回滚:tx1 发生回滚,此时tx2 做的修改仍未提交,因为只有当获取到全局锁是才会提交,避免脏数据,但是此时tx2 保持着数据的本地锁,tx1回滚要获取到本地锁,tx2超时之后,tx1获得本地锁
避免了两个分布式事务对同一个系统造成的脏数据
读隔离
本人才疏学浅没分布式脏读这方面经验,举个本地脏读的🌰:
- 本地事务脏读,商品重复售卖,事务隔离级别read uncommited
- 本地事务tx1, tx2
- tx1. 获取商品数量:1
- tx2. 获取商品数量:1
- tx1. 卖一个,更新商品数量 0
- tx2. 卖一个,更新商品数量 0
seata 读隔离
本地事务隔离级别默认 read commited,seata默认全局隔离级别为 read uncommited
特定场景下需要读取已提交,通过代理select for update
- 当查询提交包含 select for update 尝试申请全局锁,此时如果另一个分布式事务正在进行中且对需要的数据进行了修改,全局锁便会申请失败,回滚select fro update 的本地执行。
- 需要了解的是对于分布式脏读的情况必须确定什么情况下会发生,然后懂特定的脏读语句使用selec for update 优化
select for update 本身的含义先数据库上行锁然后读取
select * from consumer where id = 1 for update
此时id = 1 的数据如果没被上锁,则可以对其上锁,并获取数据
tx1 系统A,系统B
tx2 系统A,系统C
系统A 100块钱
。。。
tx1:A 修改数据库 +100 提交本地事务
tx2:A 读取当前 200
tx1:异常回滚,A 数据库恢复为 100
tx2:A 做了一些时间比较长的处理
tx2:。。。
举例失败。。。不能脏读,评论区大佬有场景吗,来一个
未完待续。。。