记功能迁移导致的事务回滚问题

背景:

由于A应用功能较单薄,并且请求量不是很大,所以为了降低维护成本和服务器成本,决定将A应用的功能迁移到B应用中。

B应用中存在通过dubbo调用A应用接口的情况,A的代码迁移到B后,原本通过dubbo调用的代码改为应用内部接口调用。

问题现象:

A应用代码迁移到B后,B应用原本正常运行的某个功能,出现部分数据未落库的问题。

问题排查:

通过查看日志,定位到报错日志是A应用迁移后的代码产生的,但是经检查,该接口代码与迁移前一致,未做改动;

进一步检查代码,发现该接口使用了@Transactional注解,并且在出现不符合预期的情况时,TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 设置了事务回滚。

原本B应用通过dubbo调用A应用的该接口,虽然B的接口中也使用了事务注解,但是出现异常情况时只会回滚A应用操作的表,并不会回滚B接口中操作的表。由于将A应用代码迁移到了B后,整个业务流程处于同一个事务中了,所以导致B中原本不会回滚的表也回滚了,出现数据未落库的问题。

解决方案:

为了使业务处理逻辑保持原样,所以需要将原本A应用代码的事务与B应用代码的事务隔离开。原本A应用的接口@Transactional注解使用的是默认配置,即propagation=REQUIRED。遂将迁移后的代码改为@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class),从而解决问题。

对于未落库的数据,通过捞取日志,对日志进行解析,构建出原本要落库的数据插入到数据库中解决。

反思:

在代码迁移过程中修改dubbo调用为应用内部调用时,就该注意到可能存在这个问题的,这里也是自己放松了警惕。当然这里也存在测试资源不足,导致测试不充分的问题。

在对历史代码进行迁移和改造时,要格外仔细和谨慎,考虑的要更全面,避免产生预料外的情况。

你可能感兴趣的:(Java,Springboot,踩坑总结,spring,分布式,java)