并发+事务处理不当引起的部分数据被提前消费

今天线上出现了一个诡异bug,部分数据被提前消费。由于业务流程保密问题,下面用例子详解

场景:现在有个需求,学校需要统计每个班,每天的考勤情况

我们用两个定时任务来解决,定时任务A插入考勤数据,定时任务B统计考勤数据

定时任务之间可能存在并发。

 

package com.test.scholl.service.impl;

// 定时任务A执行方法
public void insertAttendanceAndDetails(Attendance attendance){
    
    // 插入主表
    this.insertAttendance(attendance);

    // 插入明细表
    for(AttendanceDetail detail: attendance.getDetails()){
        this.insertDetails(detail);
    }

}

public void censusAttendance(){

    // 1.查询未统计的班级

    // 2.折算出勤比例

    // 3.更新主表状态为已统计  

}

此时注意,定时任务A中insertAttendanceAndDetails方法存在一个隐患,是啥呢?跑下程序,你会发现,该方法未受事务控制,也就是在执行完主表插入,事务自动提交,执行每条子表插入,事务自动提交。此时,如果定时任务B正好消费到定时任务A已提交数据,但数据未全的情况下,就会引发部分数据被提前消费,剩余数据永远不会被消费的问题。

为啥会没受事务控制呢?

我们首先调用的是AOP代理对象而不是目标对象,首先执行事务切面,事务切面内部通过TransactionInterceptor环绕增强进行事务的增强,即进入目标方法之前开启事务,退出目标方法时提交/回滚事务。

而insertAttendanceAndDetails方法里的this指向目标对象,因此调用this.insertDetails()将不会执行insertDetails事务切面,即不会执行事务增强

 

附上解决链接,供参考

https://www.jianshu.com/p/8ebcbacd9657

https://blog.csdn.net/dapinxiaohuo/article/details/52092447

https://blog.csdn.net/dapinxiaohuo/article/details/52092447

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章