事务可重复读采坑
程序员文章站
2023-10-16 23:18:06
1. 事务可重复读采坑 1.1. 问题 1. 今天碰到个事务幻读的情况,不容易啊,这不是事务间造成的问题,而是rpc调用产生的问题,实际上业务比较规范也不会出现这样的问题。 2. 具体情况是系统A方法a开启 事务,在事务方法中rpc调用了系统B,生成了一条订单,而之后系统A又用sql查询了这条订单, ......
1. 事务可重复读采坑
1.1. 问题
- 今天碰到个事务幻读的情况,不容易啊,这不是事务间造成的问题,而是rpc调用产生的问题,实际上业务比较规范也不会出现这样的问题。
- 具体情况是系统a方法a开启
required
事务,在事务方法中rpc调用了系统b,生成了一条订单,而之后系统a又用sql查询了这条订单,会发现根本查不到
1.2. 原因
- 通过
select @@tx_isolation;
查询mysql的事务隔离情况会发现,mysql默认是repeatable-read
可重复读,映射到代码就是在一个事务内,用同样的条件查询数据库查询到的数据是相同的,哪怕别的系统在事务期间插入了数据,你也读不到
1.3. 解决办法
- mysql使用这样的隔离级别是有道理的,避免重复读取的不准确,只要这个库都归一个系统管理,我们就可以避免我上述的问题
- 但既然我现在的遗留业务已经成为了这样的逻辑,在不能修改其它系统的前提下,我只能在代码上下功夫,我对读取订单数据的方法c设置了传播级别为
requires_new
,也就是新起一个事务,那它就不会受到父事务的影响,还要确保进入该方法前插入订单已提交就行 - 但这样带来的问题是,方法c若执行正确,但包裹了方法c的方法a中其它行报错,则不能回滚方法方法a的执行内容
- 这样我又需要写额外的补偿代码,当方法a执行错误,且问题不是在方法c时,我要跳过方法c进行方法调用补偿
1.4. 总结
- 搞的这么复杂,实际上上面的改造在可以动其他系统的情况下,最简单就是获取订单信息不应该系统a来写sql读,既然系统b管理了订单表那么关于它的增删改查都由它提供就不会产生上述问题了
推荐阅读
-
阿里分布式事务seata入门(采坑)
-
事务可重复读采坑
-
阿里分布式事务seata入门(采坑)
-
MySQL事务 InnoDB下隔离级别为可重复读 解决幻读了吗
-
高性能MySQL:04---事务之隔离级别(未提交读(脏读)、提交读(不可重复读)、可重复读(幻读)、可串行化)
-
mysql的4种事务特性,5种隔离级别,7种传播行为/ MySQL InnoDB事务隔离级别脏读、可重复读、幻读/ Spring Boot中的事务管理 隔离级别
-
MySQL InnoDB事务隔离级别脏读、可重复读、幻读
-
SqlServer事务中的可重复读和序列化隔离界别
-
事务可重复读采坑
-
MySQL事务 InnoDB下隔离级别为可重复读 解决幻读了吗