最近在生产上遇到了事务问题,此篇文章用于记录分享。
问题是这样的:该程序会依次调用两个接口,在调完第一个接口成功数据入库,调用第二个接口时,异常报错,此时需要回滚第一个接口中的数据,虽然手动回滚,但是数据依然没有被删除掉。
由于是依次调用两个不同的接口,而不是在第二个接口中调用第一个接口,所以在第二个接口中写的事务,即使程序异常回滚了,第一个接口里面的数据也不会回滚,所以采用的是下面的方法:
如图所示,假设发邮件系统报错,在捕获异常后,手动进行删除操作用以回滚,但是重点在于:
我们需要将这个delete方法创建一个新的事务,因为如果不创建新的事务,那么报错异常,会将这个delete语句操作数据库的行为也一起回滚
这个就涉及到事务的传播行为,我们需要使用
PROPAGATION_REQUIRES_NEW来创建新事务:
无论当前存不存在事务,都创建新事务。(requires_new需要新的,不管有没有,直接创建新事务),而不是使用事务的默认行为,如下图:
这样REQUIRES_NEW会新开启事务,外层事务不会影响内部事务的提交/回滚,标志REQUIRES_NEW的内部事务的异常,会影响外部事务的回滚。
除此之外,还有很重要的一点,就是不能在同一个类中写这个delete方法,自己调用自己,这样是不生效的!!!!!
由于@Transactional是基于AOP动态代理,所以写在同一个类中是不行的,要通过注入的方式,例如方法写在另一个Service层里,之后利用@Autowired注入这个Service,这样才会生效!!!!
下次会跟大家分享一下事务的传播行为,来避免出现类似的生产问题
文章转载自琢磨先生DataBase,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。