现象描述:

调用支付宝条码支付接口的时候,如果支付成功会立即更新订单状态为成功,并以订单号为主键向流水表插入一条流水;

如果支付成功,支付宝会回调我们的一个接口,这个接口同样也会更新订单状态为成功,并以订单号为主键向流水表插入一条流水;

所以,在插入订单流水之前,会先以订单号为条件查询流水是否已经插入,如果没有查到,则插入,否则直接返回。

事务环境下加锁不生效的坑

但是,在测试的时候,偶尔会出现支付流水表插入失败的情况,异常是主键重复。

经过分析,发现问题有可能是支付宝的成功回调线程走到了119行的时候,我们的同步更新线程也已经走过了119行并且还没有插入流水记录,导致两个线程都判断这条订单号对应的流水不存在,所以都插入流水导致并发问题出现。

于是,我们就加了锁

事务环境下加锁不生效的坑

再次测试,还是存在同样的报错日志,简直是百思不得其解,最后经过一个多小时的查询,终于在网上发现了问题所在,在事务内加锁不生效,再看下我们的代码确实是在事务中,那么这是为什么呢?

因为当一个线程获得锁并执行插入流水动作后,此时事务还没有提交,所以数据库中还没有这条记录,这时另外一个线程就获得锁,当然查不到这条记录,现象就是这个锁没有生效。

最后是通过代码逻辑上的修改,保证只有成功回调的线程会执行插入流水的动作,避免了并发的产生来解决的。

相关文章: