spring框架封裝了不少有用的功能和組件,便於在項目開發中快速高效的調用,其中spring的事務使用很是簡單,只須要在用到事務的地方加一行註解便可:spring
1@Transactionalsql
但越是看起來簡單的東西,就越多坑,爲什麼如此?數據庫
不是由於別人造的輪子有問題,而是咱們在用輪子的時候,只會用,不知其原理,於是不能在實際使用場景中很好的把握它。架構
spring的事務傳播行爲在實戰中是很是重要的,但90%的人只會@Transactional,在此頗有必要給你們分享一下。併發
在事務註解的參數中,咱們能夠看到有這樣的一個參數:框架
這個參數就是用來控制事務傳播行爲的,下面對這個參數進行詳細的解答每個參數表明的傳播行爲以及在講解在實際場景中應該選擇參數值。分佈式
文章提綱:高併發
Spring事務傳播行爲性能
事務傳播行爲剖析(實例)學習
參數行爲場景應用(實例)
1.Spring事務傳播行爲:
spring支持7種事務傳播行爲,肯定客戶端和被調用端的事務邊界(說得通俗一點就是多個具備事務控制的service的相互調用時所造成的複雜的事務邊界控制)下圖所示爲7鍾事務傳播機制:
傳播行爲(XML)含義
REQUIRED:表示當前方法必須在一個具備事務的上下文中運行,若有客戶端有事務在進行,那麼被調用端將在該事務中運行,不然的話從新開啓一個事務(若是被調用端發生異常,那麼調用端和被調用端事務都將回滾)。
SUPPORTS:表示當前方法沒必要須要具備一個事務上下文,可是若是有一個事務的話,它也能夠在這個事務中運行。
MANDATORY:表示當前方法必須在一個事務中運行,若是沒有事務,將拋出異常
NESTED:表示若是當前方法正有一個事務在運行中,則該方法應該運行在一個嵌套事務中,被嵌套的事務能夠獨立於被封裝的事務中進行提交或者回滾。若是封裝事務存在,而且外層事務拋出異常回滾,那麼內層事務必須回滾,反之,內層事務並不影響外層事務。若是封裝事務不存在,則同REQUIRED的同樣。
NEVER:表示當方法務不該該在一個事務中運行,若是存在一個事務,則拋出異常。
REQUIRES_NEW:表示當前方法必須運行在它本身的事務中。一個新的事務將啓動,並且若是有一個現有的事務在運行的話,則這個方法將在運行期被掛起,直到新的事務提交或者回滾才恢復執行。
NOT_SUPPORTED:表示該方法不該該在一個事務中運行。若是有一個事務正在運行,他將在運行期被掛起,直到這個事務提交或者回滾才恢復執行。
2.事務傳播行爲剖析(實例)
假設有類A的方法methodB(),有類B的方法methodB().
REQUIRED
若是B的方法methodB()的事務傳播特性是required,那麼以下圖
A.methodA()調用B的methodB()方法,那麼若是A的方法包含事務,則B的方法則不重新開啓事務,
一、 若是B的methodB()拋出異常,A的methodB()沒有捕獲,則A和B的事務都會回滾;
二、 若是B的methodB()運行期間異常會致使B的methodB()的回滾,A若是捕獲了異常,並正常提交事務,則會發生Transaction rolled back because it has been marked as rollback-only的異常。
三、 若是A的methodA()運行期間異常,則A和B的Method的事務都會被回滾
SUPPORTS
若是B的方法methodB()的事務傳播特性是supports,麼以下圖
A.methodA()調用B的methodB()方法,那麼若是A的方法包含事務,則B運行在此事務環境中,若是A的方法不包含事務,則B運行在非事務環境;
一、若是A沒有事務,則A和B的運行出現異常都不會回滾。
二、若是A有事務,A的method方法執行拋出異常,B.methodB和A.methodA都會回滾。
三、若是A有事務,B.method拋出異常,B.methodB和A.methodA都會回滾,若是A捕獲了B.method拋出的異常,則會出現異常Transactionrolled back because it has been marked as rollback-only。
MANDATORY
表示當前方法必須在一個事務中運行,若是沒有事務,將拋出異常,以下圖調用關係:
B.methodB()事務傳播特性定義爲:MANDATORY
一、若是A的methoda()方法沒有事務運行環境,則B的methodB()執行的時候會報以下異常:No existingtransaction found for transaction marked with propagation 'mandatory'
二、若是A的Methoda()方法有事務而且執行過程當中拋出異常,則A.methoda()和B.methodb()執行的操做被回滾;
三、若是A的methoda()方法有事務,則B.methodB()拋出異常時,A的methoda()和B.methodB()都會被回滾;若是A捕獲了B.method拋出的異常,則會出現異常Transaction rolled back because ithas been marked as rollback-only
NESTED
若有一下方法調用關係,如圖:
B的methodB()定義的事務爲NESTED;
一、若是A的MethodA()不存在事務,則B的methodB()運行在一個新的事務中,B.method()拋出的異常,B.methodB()回滾,但A.methodA()不回滾;若是A.methoda()拋出異常,則A.methodA()和B.methodB()操做不回。
二、 若是A的methodA()存在事務,則A的methoda()拋出異常,則A的methoda()和B的Methodb()都會被回滾;
三、 若是A的MethodA()存在事務,則B的methodB()拋出異常,B.methodB()回滾,若是A不捕獲異常,則A.methodA()和B.methodB()都會回滾,若是A捕獲異常,則B.methodB()回滾,A不回滾;
NEVER
表示事務傳播特性定義爲NEVER的方法不該該運行在一個事務環境中
有以下調用關係:
若是B.methodB()的事務傳播特性被定義爲NEVER,則若是A.methodA()方法存在事務,則會出現異常Existingtransaction found for transaction marked with propagation 'never'。
REQUIRES_NEW
表示事務傳播特性定義爲REQUIRES_NEW的方法須要運行在一個新的事務中。
若有一下調用關係:B.methodB()事務傳播特性爲REQUIRES_NEW.
一、 若是A存在事務,A.methodA()拋出異常,A.methodA()的事務被回滾,但B.methodB()事務不受影響;若是B.methodB()拋出異常,A不捕獲的話,A.methodA()和B.methodB()的事務都會被回滾。若是A捕獲的話,A.methodA()的事務不受影響但B.methodB()的事務回滾。
NOT_SUPPORTED
表示該方法不該該在一個事務中運行。若是有一個事務正在運行,他將在運行期被掛起,直到這個事務提交或者回滾才恢復執行。
若有一下調用關係圖:
若是B.methodB()方法傳播特性被定義爲:NOT_SUPPORTED。
一、 若是A.methodA()存在事務,若是B.methodB()拋出異常,A.methodA()不捕獲的話,A.methodA()的事務被回滾,而B.methodB()出現異常前數據庫操做不受影響。若是A.methodA()捕獲的話,則A.methodA()的事務不受影響,B.methodB()異常拋出前的數據操做不受影響。
3. 參數行爲場景應用(實例)
一、 在一個話費充值業務處理邏輯中,有以下圖所示操做:
業務須要扣款操做和建立訂單操做同成功或者失敗,所以,charger()和order()的事務不能相互獨立,須要包含在chargeHandle()的事務中;
經過以上需求,能夠給charge()和order()的事務傳播行爲定義成:MANDATORY
只要charge()或者order()拋出異常整個chargeHandle()都一塊兒回滾,即便chargeHandle()捕獲異常也沒用,不容許提交事務。
二、 若是業務需求沒接受到一次請求到要記錄日誌到數據庫,以下圖:
由於log()的操做無論扣款和建立訂單成功與否都要生成日誌,而且日誌的操做成功與否不影響充值處理,因此log()方法的事務傳播行爲能夠定義爲:REQUIRES_NEW.
在訂單的售後處理中,更新完訂單金額後,須要自動統計銷售報表,以下圖所示:
根據業務可知,售後是已經處理完訂單的充值請求後的功能,是對訂單的後續管理,統計報表report()方法耗時較長,所以,咱們須要設置report()的事務傳播行爲爲:NEVER,表示不適合在有事務的操做中調用,由於report()太耗時。
在銀行新增銀行卡業務中,須要執行兩個操做,一個是保存銀行卡信息,一個是登記新建立的銀行卡信息,其中登記銀行卡信息成功與否不影響銀行卡的建立。
由以上需求,咱們可知對於regster()方法的事務傳播行爲,能夠設置爲NESTED,action()事務的回滾,regster()保存的信息就沒意義,也就須要跟着回滾,而regster()的回滾不影響action()事務;insert()的事務傳播行爲能夠設置爲REQUIRED, MANDATORY,即insert()回滾事務,action()的事務必須跟着回滾。
歡迎工做一到五年的Java工程師朋友們加入Java高級架構:705127209
羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,
MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)
合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!