数据库事务原理详解-事务的嵌套
通過上面的理論知識的鋪墊,我們大致知道了數據庫事務和Spring 事務的一些屬性和特點,接下來我們通過分析一些嵌套事務的場景,來深入理解Spring 事務傳播的機制。
假設外層事務Service A 的Method A() 調用內層Service B 的Method B()PROPAGATION_REQUIRED(Spring 默認)
如果ServiceB.MethodB() 的事務級別定義為PROPAGATION_REQUIRED,那么執行ServiceA.MethodA() 的時候Spring 已經起了事務,這時調用ServiceB.MethodB(),ServiceB.MethodB() 看到自己已經運行在ServiceA.MethodA() 的事務內部,就不再起新的事務。
假如ServiceB.MethodB() 運行的時候發現自己沒有在事務中,他就會為自己分配一個事務。
這樣,在ServiceA.MethodA() 或者在ServiceB.MethodB() 內的任何地方出現異常,事務都會被回滾。
PROPAGATION_REQUIRES_NEW比如我們設計ServiceA.MethodA() 的事務級別為PROPAGATION_REQUIRED,ServiceB.MethodB() 的事務級別為PROPAGATION_REQUIRES_NEW。
那么當執行到ServiceB.MethodB() 的時候,ServiceA.MethodA() 所在的事務就會掛起,ServiceB.MethodB() 會起一個新的事務,等待ServiceB.MethodB() 的事務完成以后,它才繼續執行。
他與PROPAGATION_REQUIRED 的事務區別在于事務的回滾程度了。因為ServiceB.MethodB() 是新起一個事務, 那么就是存在兩個不同的事務。如果ServiceB.MethodB() 已經提交, 那么ServiceA.MethodA() 失敗回滾,ServiceB.MethodB() 是不會回滾的。如果ServiceB.MethodB() 失敗回滾,如果他拋出的異常被ServiceA.MethodA() 捕獲,ServiceA.MethodA() 事務仍然可能提交(主要看B 拋出的異常是不是A 會回滾的異常)。
PROPAGATION_SUPPORTS
假設ServiceB.MethodB() 的事務級別為PROPAGATION_SUPPORTS,那么當執行到ServiceB.MethodB()時,如果發現ServiceA.MethodA()已經開啟了一個事務,則加入當前的事務,如果發現ServiceA.MethodA()沒有開啟事務,則自己也不開啟事務。這種時候,內部方法的事務性完全依賴于最外層的事務。
PROPAGATION_NESTED
現在的情況就變得比較復雜了, ServiceB.MethodB() 的事務屬性被配置為PROPAGATION_NESTED, 此時兩者之間又將如何協作呢? ServiceB.MethodB() 如果rollback, 那么內部事務(即ServiceB.MethodB()) 將回滾到它執行前的SavePoint而外部事務(即ServiceA.MethodA()) 可以有以下兩種處理方式:
捕獲異常,執行異常分支邏輯
void MethodA() {try {ServiceB.MethodB();} catch (SomeException) {// 執行其他業務, 如ServiceC.MethodC();} }這種方式也是嵌套事務最有價值的地方, 它起到了分支執行的效果, 如果ServiceB.MethodB()失敗, 那么執行ServiceC.MethodC(), 而ServiceB.MethodB()已經回滾到它執行之前的SavePoint, 所以不會產生臟數據(相當于此方法從未執行過),這種特性可以用在某些特殊的業務中, 而PROPAGATION_REQUIRED 和PROPAGATION_REQUIRES_NEW 都沒有辦法做到這一點。
外部事務回滾/提交代碼不做任何修改, 那么如果內部事務(ServiceB.MethodB())rollback, 那么首先ServiceB.MethodB() 回滾到它執行之前的SavePoint(在任何情況下都會如此), 外部事務( 即ServiceA.MethodA()) 將根據具體的配置決定自己是commit 還是rollback。
另外三種事務傳播屬性基本用不到,在此不做分析。
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的数据库事务原理详解-事务的嵌套的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring 中的隔离级别
- 下一篇: linux cmake编译源码,linu