![](/img/trans.png)
[英]Differences between requires_new and nested propagation in Spring transactions
[英]Differences in behaviour of REQUIRES_NEW and NESTED propagation in Spring transactions
前言
首先:
它與Spring事務中的requires_new和嵌套傳播之間的差異不重復 - 我讀了它,但我沒有找到我的問題的答案
題:
在閱讀了我提到的主題之后,我理解了物理交易數量中傳播水平的主要區別:
2 db事務 - 對於外部和內部方法的REQUIRES_NEW
1 db transaction - 用於NESTED
for outer和for inner方法。 如果底層數據庫不支持保存點,它將無法工作
但是看起來邏輯從我的觀點來看是相同的。
如何理解在實踐中使用哪個級別? 任何用例了解它? 方便的行為差異的例子?
PS
我想其他事務差異有一些可見性,因為不同的事務提交時間。
PS2
另外我認為有性能差異:
@Transactional
public void outer(){
for(int i=0;i<100500;i++){
inner();
}
}
@Transactional
public void inner(){
//some logic
}
對於那種情況,NESTED會更好,因為1長的物理交易而不是100500 + 1
我看到的巨大差異:
在嵌套的情況下:
在requires_new的情況下:
在性能方面 ,如果其他因素不重要,您可以在交易規模和交易數量之間找到收支平衡點。 如果嵌套比requires_new快,那么問題沒有一般的答案。
正如你的例子所示,如果inner()
有:
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void inner(){
//some logic
}
然后,如果它從outer()
循環中的第二個調用中拋出異常,則第一個調用的更改將已經由其REQUIRES_NEW
提交。
如果inner()
有:
@Transactional(propagation=Propagation.NESTED)
public void inner(){
//some logic
}
然后將回滾第一次調用的更改 - 因為outer()
沒有catch塊。
inner()
上的傳播級別真正開始重要的一點是,如果outer()
循環將處理inner()
異常:
@Transactional
public void outer() {
for (int i = 0; i < 100500; i++) {
try {
inner();
} catch (Exception ex) {
// Report and continue
}
}
// Something else that could fail
}
很明顯, REQUIRES_NEW
和NESTED
只會保留對成功的inner()
調用的更改。 但關鍵的區別在於,使用NESTED
,如果outer()
存在后續故障,仍然可以選擇將其全部丟棄。
如您所說,另一個因素是可伸縮性 - 某些數據庫可能無法理解具有NESTED
傳播的父事務的大小。
此外,它可能值得一說 - 盡管我懷疑它只是為了明確示例。 直接調用this.inner()
繞過Spring事務顧問。 需要允許注入“建議的bean”以允許@Transactional
注釋在調用之前和之后執行其魔法 - 例如nextAutowiredBean.inner()
。
如果你的內部邏輯獨立於外部邏輯,則使用Requires_new,如果不使用嵌套。
例如,您的外部方法可能正在處理包含大量記錄的作業,並調用持久作業狀態的內部方法(進度,警告和驗證錯誤)。 您希望內部方法事務是獨立的,並且其數據庫更改將立即保存,以便系統的其他部分可以顯示進度。 如果外部方法遇到異常,它的事務將回滾,但內部方法的事務不會。
當您需要對外部和內部更改進行持久化或同時回滾兩者時,您可能希望使用嵌套或從屬事務。 例如,您需要創建一個新用戶(使用“外部”服務)並保存其地址(使用“內部”服務)。 如果您的要求是用戶必須擁有地址,那么如果保存用戶或地址失敗,您希望回滾兩個更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.