事務傳播

本節描述了 Spring 中事務傳播的一些語義。請注意,本節不是對事務傳播的正式介紹。相反,它詳細介紹了 Spring 中關於事務傳播的一些語義。

在 Spring 管理的事務中,請注意物理事務和邏輯事務之間的區別,以及傳播設定如何應用於這種區別。

理解 PROPAGATION_REQUIRED

tx prop required

PROPAGATION_REQUIRED 強制使用一個物理事務,如果當前作用域尚無事務,則在本地使用;如果存在為更大作用域定義的“外部”事務,則參與其中。在同一執行緒內的常見呼叫棧安排中(例如,一個將任務委託給多個倉庫方法的 Service Facade,其中所有底層資源都必須參與 Service 級別的事務),這是一個不錯的預設設定。

預設情況下,參與事務會繼承外部作用域的特性,默默忽略本地的隔離級別、超時值或只讀標誌(如果有的話)。如果您希望在參與不同隔離級別的現有事務時拒絕隔離級別宣告,請考慮將事務管理器上的 validateExistingTransactions 標誌切換為 true。這種非寬鬆模式也會拒絕只讀不匹配(即嘗試參與只讀外部作用域的內部讀寫事務)。

當傳播設定為 PROPAGATION_REQUIRED 時,對於應用了該設定的每個方法都會建立一個邏輯事務作用域。每個這樣的邏輯事務作用域都可以獨立確定僅回滾狀態,而外部事務作用域在邏輯上獨立於內部事務作用域。在標準的 PROPAGATION_REQUIRED 行為下,所有這些作用域都對映到同一個物理事務。因此,在內部事務作用域中設定的僅回滾標記確實會影響外部事務實際提交的機會。

然而,如果在內部事務作用域設定了僅回滾標記的情況下,外部事務本身尚未決定回滾,因此回滾(由內部事務作用域悄然觸發)是意外的。此時會丟擲相應的 UnexpectedRollbackException。這是預期行為,以確保事務的呼叫者永遠不會被誤導,以為事務已提交而實際上並未提交。因此,如果一個內部事務(外部呼叫者不知道)悄然將事務標記為僅回滾,外部呼叫者仍然會呼叫提交。外部呼叫者需要接收一個 UnexpectedRollbackException 來清楚地表明發生了回滾。

理解 PROPAGATION_REQUIRES_NEW

tx prop requires new

PROPAGATION_REQUIRED 相反,PROPAGATION_REQUIRES_NEW 始終為每個受影響的事務作用域使用獨立的物理事務,絕不參與外部作用域的現有事務。在這種安排下,底層資源事務是不同的,因此可以獨立提交或回滾,外部事務不受內部事務回滾狀態的影響,並且內部事務的鎖在完成後立即釋放。這種獨立的內部事務也可以宣告自己的隔離級別、超時和只讀設定,而不繼承外部事務的特性。

附加到外部事務的資源將保持繫結狀態,而內部事務獲取自己的資源,例如新的資料庫連線。如果多個執行緒具有活動的外部事務並等待為其內部事務獲取新連線,而連線池無法再提供此類內部連線,這可能導致連線池耗盡,並可能導致死鎖。除非您的連線池大小合適,且至少比並發執行緒數多 1,否則不要使用 PROPAGATION_REQUIRES_NEW

理解 PROPAGATION_NESTED

PROPAGATION_NESTED 使用單個物理事務和多個可以回滾到的儲存點。這種部分回滾允許內部事務作用域觸發其作用域的回滾,而外部事務儘管部分操作已回滾,仍能繼續物理事務。此設定通常對映到 JDBC 儲存點,因此僅適用於 JDBC 資源事務。請參閱 Spring 的 DataSourceTransactionManager