源碼分析:Spring 事務(wù) @Transactional Timeout 參數(shù)不生效的問題

本文通過分析Spring 事務(wù)的源碼,說明@Transactional Timeout 參數(shù)設(shè)置的一些問題。

從問題開始,下面兩段代碼,事務(wù)是否都能正常的回滾?

timeout 參數(shù)大于3

代碼片段1

    @Transactional(rollbackFor = Exception.class , propagation = Propagation.REQUIRED,timeout = 3)
    public int timeout(int timeout,int blogId){
        jdbcTemplate.execute("DELETE FROM blog where id = "+blogId);
        Sleep.second(timeout);
        jdbcTemplate.execute("SELECT 1");
        return timeout;
    }

代碼片段2

    @Transactional(rollbackFor = Exception.class , propagation = Propagation.REQUIRED,timeout = 3)
    public int timeout(int timeout , int blogId){
        jdbcTemplate.execute("DELETE FROM blog where id = "+blogId);
        Sleep.second(timeout);
        return timeout;
    }

按照我們的認(rèn)知,上面的代碼都應(yīng)該因?yàn)槌瑫r(shí)拋出異常從而觸發(fā) rollback ,但是實(shí)際運(yùn)行結(jié)果是 代碼片段2 不會(huì)回滾,如果在生產(chǎn)環(huán)境意味著數(shù)據(jù)會(huì)真實(shí)的被刪除

帶著問題來看源碼

  1. 首先我們從Timeout的異常堆棧追蹤到異常拋出的代碼
1.png
  1. 定位到ResourceHolderSupport#checkTransactionTimeout 方法,查看源碼
2.png

通過源碼可以看到,源碼通過一個(gè) dealline (Date) 與當(dāng)前時(shí)間比較來判斷是否超時(shí),那么這會(huì)就產(chǎn)生了兩個(gè)疑問:

  • dealline 在哪里設(shè)置的?
  • 什么時(shí)候調(diào)用checkTransactionTimeout?
  1. 跟蹤 dealline 屬性,找到設(shè)置的方法 ResourceHolderSupport#setTimeoutInMillis,通過Debug面板,追蹤調(diào)用堆棧,可以定位到DataSourceTransactionManager#doBegin方法
3.png
  1. 查看 DataSourceTransactionManager#doBegin 方法,定位到設(shè)置timeout的代碼端,到這里我們第一個(gè)問題得到了答案


    4.png
  2. 通過ResourceHolderSupport#checkTransactionTimeout堆棧找到調(diào)用方法

    • DataSourceUtils#applyTimeout
    • JdbcTemplate#applyStatementSettings
  • JdbcTemplate#execute
5.png
6.png
7.png

從這里就能清楚的知道, checkTransactionTimeout 是在每次執(zhí)行SQL的時(shí)候被調(diào)用的,這也就能說明為什么代碼片段1可以正常回滾了,因?yàn)榇a片段1在最后執(zhí)行了一條無意義的SQL “SELECT 1” 觸發(fā)了 checkTransactionTimeout 的檢查。

整個(gè)檢查過程抽象為流程圖就是下面這樣

process.png

本文源碼地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring 事務(wù)屬性分析 事務(wù)管理對(duì)于企業(yè)應(yīng)用而言至關(guān)重要。它保證了用戶的每一次操作都是可靠的,即便出現(xiàn)了異常的...
    壹點(diǎn)零閱讀 1,380評(píng)論 0 2
  • 原文出處: 張開濤 數(shù)據(jù)庫(kù)事務(wù)概述 事務(wù)首先是一系列操作組成的工作單元,該工作單元內(nèi)的操作是不可分割的,即要么所有...
    程序員黃小斜閱讀 311評(píng)論 0 0
  • 原文出處: 張開濤 本系列文章將整理到我在GitHub上的《Java面試指南》倉(cāng)庫(kù),更多精彩內(nèi)容請(qǐng)到我的倉(cāng)庫(kù)里查看...
    da3acf50377b閱讀 248評(píng)論 0 0
  • 前言 很多人認(rèn)為事務(wù)很簡(jiǎn)單,但是往往在工作中遇到一些事務(wù)的坑(尤其是事務(wù)方法中嵌套其它事務(wù)方法一起使用時(shí))之后,我...
    Java旺閱讀 527評(píng)論 0 0
  • Spring AOP應(yīng)用于多數(shù)場(chǎng)景 緩存 權(quán)限 懶加載 日志 事務(wù) 。。。 這一篇將通過AOP源碼的實(shí)現(xiàn)層面,結(jié)合...
    進(jìn)擊的阿黑閱讀 829評(píng)論 0 2

友情鏈接更多精彩內(nèi)容