併發+事務處理不當引起的部分數據被提前消費

今天線上出現了一個詭異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

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