最近在项目中发现一个比较严重的问题,当然之前也意识到了,已更正,不过还没上到生产环境,但在业务中发现了其巨大的威力。
大概代码结构如下:
@Transaction(REQUES_NEW)
A() {
for() {
B();
}
}
B() {
some code;
C();
some DB update actions;
}
@Transaction(REQUES_NEW)
C() {
call 第三方API,插入业务数据并记log到DB
}
最近发现由于B方法中some code中一些代码运行异常抛出没catch导致事务的回滚,而又由于B方法在for循环中,会导致所有循环到的全部回滚,而这里面会有成功的情况,其实不应该回滚的。另外,也看出异常处理也有问题,应该try catch起来的。所以导致很多数据已经比较久的没有被更新到,当发现以后,还是很严重的,毕竟业务人员是比较关心C方法中call API的返回结果的,当时也被吓了一跳,这个是事务引起的第一次心跳事件,认识到事务使用不当会造成业务上的“乱杀”。
之后我们找到那条处理不了的循环数据并做了手动处理,然后再调用相关方法,发现此时因为事务加在for循环下,而且堆积了大量的数据,那么此时循环执行完的时间会比较久,而且之后事务一次性commit的数据会相当庞大,那么此次事务就会很重,给DB造成的压力也会很重,而且一旦再出现某条数据处理不了,那么就会再次出现上面的问题,而且在事务未提交之前是无法立刻看到数据更新的效果的,所以只能等,那等的时候就是事务引起的第二次心跳事件,整个人都不好了,认识到事务使用不当加异常处理不到位会造成业务上的“风险”和“不必要的巨大压力”。
此时应该这样优化:
A() {
for() {
B();
}
}
@Transaction(REQUES_NEW)
B() {
try {
some code;
C();
some DB update actions;
} catch() {
记log,发邮件通知相关support人员去处理等
}
}
@Transaction(REQUES_NEW)
C() {
call 第三方API,插入业务数据并记log到DB
}
事务这块还要继续学习,例如:不同类型的区别和使用场景等。也是很有研究价值和业务价值的一个技术啦。