Spring @transactional注解声明式事务

前言

发版前一天,遇到了一个乐观锁问题。
产生乐观锁,肯定是同一时间,存在两个或者多个事务对同一条数据进行修改。假如有事务A和事务B,先commit的事务会成功,而另外一个事务就会失败。

这里记录一下遇到的问题,以及解决方法和过程

环境

spring data jpa
使用了@version + @transactional来进行事务管理和保证数据唯一

问题

退款过程,

对接了微信,易宝,支付宝。
微信,易宝机制类似,退款成功之后,会调我们另外一个回调方法。而支付宝退款没有回调我们。

然后,退款成功,走我们自己回调,发现支付宝总是会报一个乐观锁的错,也就是存在多个事务再对同一条数据操作。而微信和易宝都是正确的。

问题来了,到底是哪里同时对一条数据操作了两次???
带着这个思路找问题。

首先,走一遍退款流程,拿到退款过程中执行的sql!(这一步最关键)
然后,我们发现确实执行了两次update,修改的是同一条数据(同一天订单)。
接着,对比两条sql,看修改的是哪一个字段? 终于,发现都修改了字段refunding(该字段用来标识退款中)。第一条修改为false,第二条修改为true。

。。。。。。
接着,该当事人(我)出马了,马上找到修改这个值的地方,果然,我在退款的时候开启了一个事务A,A中修改了refunding=true,但是没有提交事务A,又发了一个http请求1去退款,当http请求1拿到返回结果,事务A才会提交。而支付宝退款,马上调了回调方法,在回调方法里面,又将refunding修改为false。回调方法开启了另外一个事务B。事务A修改了refunding的值,还没提交;这个时候事务B又去修改了一次,最后只有一个事务成功了,另外一个失败了。。。

因为中午马上要发版本,这个bug还没有解决,涛哥和师兄都来帮忙找问题。。。。还是大佬们找bug有经验。

解决完bug,顺顺利利发了版本。QAQ

解决问题

目前解决问题办法:在事务A修改refunding值时,直接将事务提交,再去发http退款请求,解析退款结果,如果请求失败,手动事务回滚(事务A提交了,肯定就回滚不了了,需要自己修改数据)。

总结

如果存在异步调用,或者多次http请求,那么一定要注意@transactional注解的使用。并不是单纯的加上事务就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值