首页天道酬勤spring事务回滚注解,spring注解作用

spring事务回滚注解,spring注解作用

张世龙 05-06 01:32 24次浏览

最近,在组织团队内的技术训练中,与ggdbl共享的事务和写入数据库相关联的case (错误)是代表性的。 使用事务,要小心!

一.故障现象

车辆交付履约流程的两个节点(工程项目) a和b、a修改一个数据记录(item ),向b发送消息,b也修改item。

故障现象可能会导致a未成功修复名为item的数据,日志中可能会指示a已成功修复数据item!

让我们来看看具体的代码实现。 下图为工序a代码,3个红框依次动作。

1、办公

2、修改工单记录item

3、向下游节点发送mq消息

下图为下游消耗mq消息的节点b,红框表示使用JPA技术修改数据记录item

二.原因分析

这个过程一共经历了五个步骤,见下图

1、节点a打开事务处理,修改数据表中的数据item

2、A向B发送QQ消息,做其他事情,提交事务

3、节点b、消费mq消息

4、节点b读取数据item

5、节点b修改内存中数据item的部分字段,并写回数据库

请注意,步骤1、2位于一个事务中。 作为可能,在步骤1、2的事务已完成提交之前,b节点将接收mq消息并执行步骤4,读取item数据。 由于处于数据库事务隔离级别,在这种情况下,步骤4中读取的数据不是步骤1中由a节点编写的,而是脏数据。 如果在步骤5中重新写入数据,旧数据可能会复盖用a写入的新数据。

这里有两个细分的场景

1、在步骤1、步骤5中修改相同的字段。 在这种情况下,在步骤4中读取脏数据

2、在步骤1、步骤5中修改不同的字段。 在第4步中,我阅读了col2字段中的oldvalue。 第5步旨在更改col3的值,但使用默认的jpa或mybatis书写方法会将col2的oldvalue更新到数据库中。

在典型的ORMapping框架中,使用vo对象写入数据库记录。 未更改的字段不会更新,但在步骤4中读取数据后,在步骤1中更改了数据item。 这种默认的库写入方法会检查记录更改并更新col2字段中的值。 这样就出现了旧值覆盖新值的问题。

三、解决办法

1、考虑到实施成本,只要修改不同的字段,就不存在竞争关系。 只需将更新字段指定为步骤5中库写入的一部分,即可快速解决此问题。 实际上,在生产环境中选择的这个方案也会暂时修复。

2、解决方案1显然不优秀。 更好的方法是在步骤2中发送mq消息并退出办公室,在步骤1中操作commit,然后发送mq消息。 这种方法包括组织一些逻辑(业务代码包括不少if……else )、更改代码。 如果这样的处理还不完美,执行了步骤1,步骤2失败了怎么办? 在此,您可能需要添加代码工作以确保步骤2成功执行。

3、业务压力小的情况下,也可以考虑从数据库事务隔离层面解决这个问题。

4、业务上需要从第一步到第五步强匹配时,理解分布式事务

33559 www.Jian Shu.com/p/16 B1 BAF 015 e 8

seata全局锁,seata分布式事务不生效