Spring事務傳播特性

Spring事務屬性的種類:傳播行爲、隔離級別、只讀和事務超時

1.傳播行爲定義了被調用方法的事務邊界

傳播行爲 意義
PROPERGATION_MANDATORY 表示方法必須運行在一個事務中,如果當前事務不存在,就拋出異常
PROPAGATION_NESTED 表示如果當前事務存在,則方法應該運行在一個嵌套事務中。否則,它看起來和 PROPAGATION_REQUIRED 看起來沒什麼倆樣
PROPAGATION_NEVER 表示方法不能運行在一個事務中,否則拋出異常
PROPAGATION_NOT_SUPPORTED 表示方法不能運行在一個事務中,如果當前存在一個事務,則該方法將被掛起
PROPAGATION_REQUIRED 表示當前方法必須運行在一個事務中,如果當前存在一個事務,那麼該方法運行在這個事務中,否則,將創建一個新的事務
PROPAGATION_REQUIRES_NEW 表示當前方法必須運行在自己的事務中,如果當前存在一個事務,那麼這個事務將在該方法運行期間被掛起
PROPAGATION_SUPPORTS 表示當前方法不需要運行在一個是事務中,但如果有一個事務已經存在,該方法也可以運行在這個事務中

2.隔離級別
在操作數據時可能帶來 3 個副作用,分別是髒讀、不可重複讀、幻讀。爲了避免這 3 種副作用的發生,在標準的 SQL 語句中定義了 4 種隔離級別,分別是未提交讀、已提交讀、可重複讀、可序列化。而在 Spring 事務中提供了 5 種隔離級別來對應在 SQL 中定義的 4 種隔離級別,如下:

隔離級別 意義
ISOLATION_DEFAULT 使用後端數據庫默認的隔離級別
ISOLATION_READ_UNCOMMITTED 允許讀取未提交的數據(對應未提交讀),可能導致髒讀、不可重複讀、幻讀
ISOLATION_READ_COMMITTED 允許在一個事務中讀取另一個已經提交的事務中的數據(對應已提交讀)。可以避免髒讀,但是無法避免不可重複讀和幻讀
ISOLATION_REPEATABLE_READ 一個事務不可能更新由另一個事務修改但尚未提交(回滾)的數據(對應可重複讀)。可以避免髒讀和不可重複讀,但無法避免幻讀
ISOLATION_SERIALIZABLE 這種隔離級別是所有的事務都在一個執行隊列中,依次順序執行,而不是並行(對應可序列化)。可以避免髒讀、不可重複讀、幻讀。但是這種隔離級別效率很低,因此,除非必須,否則不建議使用。

補充:
何爲髒讀、不可重複讀、幻讀。
(1) 髒讀: 髒讀發生在一個事務A讀取了被另一個事務B修改,但是還未提交的數據。假如B回退,則事務A讀取的是無效的數據。這跟不可重複讀類似,但是第二個事務不需要執行提交.
(2) 不可重複讀: 在多版本並行控制機制中,當一個遇到提交衝突的事務需要回退但卻被釋放時,會發生不可重複讀問題. 在基於鎖的並行控制方法中,如果在執行select時不添加讀鎖,就會發生不可重複讀問題.
不可重複讀的重點是修改: 同樣的條件, 你讀取過的數據, 再次讀取出來發現值不一樣了.在一個事務中前後兩次讀取的結果並不致,導致了不可重複讀.
(3) 幻讀: 幻讀發生在當兩個完全相同的查詢執行時,第二次查詢所返回的結果集跟第一個查詢不相同.幻讀的重點在於新增或者刪除 (數據條數變化)。同樣的條件, 第1次和第2次讀出來的記錄數不一樣

3 只讀

如果在一個事務中所有關於數據庫的操作都是隻讀的,也就是說,這些操作只讀取數據庫中的數據,而並不更新數據,那麼應將事務設爲只讀模式( READ_ONLY_MARKER ) , 這樣更有利於數據庫進行優化 。
因爲只讀的優化措施是事務啓動後由數據庫實施的,因此,只有將那些具有可能啓動新事務的傳播行爲 (PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事務標記成只讀纔有意義。
如果使用 Hibernate 作爲持久化機制,那麼將事務標記爲只讀後,會將 Hibernate 的 flush 模式設置爲 FULSH_NEVER, 以告訴 Hibernate 避免和數據庫之間進行不必要的同步,並將所有更新延遲到事務結束。

4. 事務超時
如果一個事務長時間運行,這時爲了儘量避免浪費系統資源,應爲這個事務設置一個有效時間,使其等待數秒後自動回滾。與設置“只讀”屬性一樣,事務有效屬性也需要給那些具有可能啓動新事物的傳播行爲的方法的事務標記成只讀纔有意義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章