Transactional碰上async

業(yè)務(wù)上線后出現(xiàn)了一個bug: 用戶配置/刪除課程時瞭亮,根據(jù)已配置課程數(shù)據(jù)生成欄目樹時好時壞家乘,具體表現(xiàn)為:某種時刻刷新的欄目樹是數(shù)據(jù)未入庫之前的舊數(shù)據(jù)蝗羊。但是全量刷新類目接口穩(wěn)定不報錯,兩個公用一個接口仁锯。

查詢具體代碼發(fā)現(xiàn)耀找,刷新類目接口是在課程配置@Transactional中調(diào)用了@async調(diào)用的異步方法,分析业崖,很有可能是這兒導(dǎo)致野芒,數(shù)據(jù)未commit完畢,異步刷新類目方法已經(jīng)調(diào)用執(zhí)行完畢了双炕。

其中stackoverflow上同樣有人提出了相同的問題:

https://stackoverflow.com/questions/51833306/using-async-inside-a-transaction-in-spring-application

具體的解決辦法狞悲,考慮有兩種:

  1. 使用event事件機(jī)制,當(dāng)數(shù)據(jù)全部更新完畢后通知異步方法執(zhí)行妇斤,這是基于觀察者模式
  2. 使用TransactionSynchronizationManager摇锋,重寫其中的 afterCommit 方法丹拯,標(biāo)明在數(shù)據(jù)commit完畢后執(zhí)行。

具體偽代碼實(shí)現(xiàn)如下:

public class CourseServiceImpl implements CourseService { 
    
    /**
     * 配置課程
     */
    public void addRealmCourseList(){
     //更新數(shù)據(jù)庫操作
        update();
     //調(diào)用異步方式
       executeAfterTransactionCommits(()->{
           //具體異步方法
          ...
        });
    }
    
    /**
     * commit之后執(zhí)行
     */
    private void executeAfterTransactionCommits(Runnable task) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                task.run();
            }
        });
    }
}

值得注意的是乱投,除去這種異常case之外咽笼,@Transactional@Async聯(lián)合使用還會導(dǎo)致設(shè)置的Transaction注解不生效。原因其實(shí)也很簡單:

  1. Spring 實(shí)現(xiàn)這兩個注解的方式都是通過AOP戚炫。
  2. 在實(shí)現(xiàn)時剑刑,Async注解強(qiáng)制覆蓋AOP的order為最小值(它認(rèn)為Async應(yīng)該是執(zhí)行的AOP鏈中的第一個advisor)
  3. 但是在實(shí)現(xiàn)Transactional注解時,卻沒有覆蓋order双肤,這意味著它仍然為默認(rèn)的Integer.MAX_VALUE施掏,order可配置。所以異步切面會先于事務(wù)切面執(zhí)行茅糜。
  4. 假設(shè)@Transactional能先于Async切面執(zhí)行七芭,但由于spring事務(wù)管理依賴的是ThreadLocal,所以在開啟的異步線程里面感知不到事務(wù)蔑赘,說細(xì)點(diǎn)就是在Spring開啟事務(wù)之后狸驳,會設(shè)置一個連接到當(dāng)前線程,但這個時候又開啟了一個新線程缩赛,執(zhí)行實(shí)際的SQL代碼時耙箍,通過ThreadLocal獲取不到連接就會開啟新連接,也不會設(shè)置autoCommit酥馍,所以這個函數(shù)整體將沒有事務(wù)辩昆。

其中,在spring源碼中同樣有人提到了這樣一個issue旨袒,目前已經(jīng)關(guān)閉:

https://github.com/spring-projects/spring-framework/issues/11806

由此可見汁针,當(dāng)我們業(yè)務(wù)中有需要Transaction與async同時使用時,一定要小心使用砚尽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末施无,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子必孤,更是在濱河造成了極大的恐慌帆精,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隧魄,死亡現(xiàn)場離奇詭異卓练,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)购啄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評論 2 385
  • 文/潘曉璐 我一進(jìn)店門襟企,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狮含,你說我怎么就攤上這事顽悼÷瘢” “怎么了?”我有些...
    開封第一講書人閱讀 157,019評論 0 348
  • 文/不壞的土叔 我叫張陵蔚龙,是天一觀的道長冰评。 經(jīng)常有香客問我,道長木羹,這世上最難降的妖魔是什么甲雅? 我笑而不...
    開封第一講書人閱讀 56,443評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮坑填,結(jié)果婚禮上抛人,老公的妹妹穿的比我還像新娘。我一直安慰自己脐瑰,他們只是感情好妖枚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苍在,像睡著了一般绝页。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寂恬,一...
    開封第一講書人閱讀 49,798評論 1 290
  • 那天抒寂,我揣著相機(jī)與錄音,去河邊找鬼掠剑。 笑死,一個胖子當(dāng)著我的面吹牛郊愧,可吹牛的內(nèi)容都是我干的朴译。 我是一名探鬼主播,決...
    沈念sama閱讀 38,941評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼属铁,長吁一口氣:“原來是場噩夢啊……” “哼眠寿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起焦蘑,我...
    開封第一講書人閱讀 37,704評論 0 266
  • 序言:老撾萬榮一對情侶失蹤盯拱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后例嘱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狡逢,經(jīng)...
    沈念sama閱讀 44,152評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評論 2 327
  • 正文 我和宋清朗相戀三年拼卵,在試婚紗的時候發(fā)現(xiàn)自己被綠了奢浑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,629評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡腋腮,死狀恐怖雀彼,靈堂內(nèi)的尸體忽然破棺而出壤蚜,到底是詐尸還是另有隱情,我是刑警寧澤徊哑,帶...
    沈念sama閱讀 34,295評論 4 329
  • 正文 年R本政府宣布袜刷,位于F島的核電站,受9級特大地震影響莺丑,放射性物質(zhì)發(fā)生泄漏著蟹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評論 3 313
  • 文/蒙蒙 一窒盐、第九天 我趴在偏房一處隱蔽的房頂上張望草则。 院中可真熱鬧,春花似錦蟹漓、人聲如沸炕横。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽份殿。三九已至,卻和暖如春嗽交,著一層夾襖步出監(jiān)牢的瞬間卿嘲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評論 1 266
  • 我被黑心中介騙來泰國打工夫壁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拾枣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,333評論 2 360
  • 正文 我出身青樓盒让,卻偏偏與公主長得像梅肤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子邑茄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評論 2 348

推薦閱讀更多精彩內(nèi)容