1. 程式人生 > >spring 事務傳播行為和事務隔離級別

spring 事務傳播行為和事務隔離級別

1、Spring宣告式事務

宣告式事務(declarative transaction management)是Spring提供的對程式事務管理的方式之一。 Spring的宣告式事務顧名思義就是採用宣告的方式來處理事務。這裡所說的宣告,就是指在配置檔案中申明。用在Spring配置檔案中宣告式的處理事務來代替程式碼式的處理事務。這樣的好處是,事務管理不侵入開發的元件,具體來說,業務邏輯物件就不會意識到正在事務管理之中,事實上也應該如此,因為事務管理是屬於系統層面的服務,而不是業務邏輯的一部分,如果想要改變事務管理策劃的話,也只需要在定義檔案中重新配置即可;在不需要事務管理的時候,只要在設定檔案上修改一下,即可移去事務管理服務,無需改變程式碼重新編譯,這樣維護起來極其方便。 Spring使用
AOP
來完成宣告式的事務管理,因而宣告式事務是以方法為單位,Spring的事務屬性自然就在於描述事務應用至方法上的策略,在Spring中事務屬性有以下引數:
屬性 型別 描述
列舉型:Propagation 可選的傳播性設定
isolation 列舉型:Isolation 可選的隔離性級別(預設值:ISOLATION_DEFAULT)
readOnly 布林型 讀寫型事務 vs. 只讀型事務
timeout int型(以秒為單位) 事務超時
rollbackFor 一組Class類的例項,必須是Throwable的子類 一組異常類,遇到時 必須 進行回滾。預設情況下checked exceptions不進行回滾,僅unchecked exceptions(即RuntimeException的子類)才進行事務回滾。
rollbackForClassname 一組Class類的名字,必須是Throwable的子類 一組異常類名,遇到時 必須 進行回滾
noRollbackFor 一組Class類的例項,必須是Throwable的子類 一組異常類,遇到時 必須不 回滾。
noRollbackForClassname 一組Class類的名字,必須是Throwable的子類 一組異常類,遇到時 必須不 回滾

2、Spring傳播行為

REQUIRED 業務方法需要在一個事務中執行,如果方法執行時,已處在一個事務中,那麼就加入該事務,否則自己建立一個新的事務.這是spring預設的傳播行為.

SUPPORTS 如果業務方法在某個事務範圍內被呼叫,則方法成為該事務的一部分,如果業務方法在事務範圍外被呼叫,則方法在沒有事務的環境下執行.

MANDATORY 只能在一個已存在事務中執行,業務方法不能發起自己的事務,如果業務方法在沒有事務的環境下呼叫,就拋異常

REQUIRES_NEW 業務方法總是會為自己發起一個新的事務,如果方法已執行在一個事務中,則原有事務被掛起,新的事務被建立,直到方法結束,新事務才結束,原先的事務才會恢復執行.
NOT_SUPPORTED 宣告方法需要事務,如果方法沒有關聯到一個事務,容器不會為它開啟事務.如果方法在一個事務中被呼叫,該事務會被掛起,在方法呼叫結束後,原先的事務便會恢復執行.
NEVER 宣告方法絕對不能在事務範圍內執行,如果方法在某個事務範圍內執行,容器就拋異常.只有沒關聯到事務,才正常執行.

NESTED 如果一個活動的事務存在,則執行在一個巢狀的事務中.如果沒有活動的事務,則按REQUIRED屬性執行.它使用了一個單獨的事務, 這個事務擁有多個可以回滾的保證點.內部事務回滾不會對外部事務造成影響, 它只對DataSourceTransactionManager 事務管理器起效.

 .詳細解釋如下:

Required:預設的事務傳播行為,表示必須有邏輯事務,否則新建一個事務,使用PROPAGATION_REQUIRED指定,表示如果當前存在一個邏輯事務,則加入該邏輯事務,否則將新建一個邏輯事務:

RequiresNew:建立新的邏輯事務,使用PROPAGATION_REQUIRES_NEW指定,表示每次都建立新的邏輯事務(物理事務也是不同的)因此外部事務可以不受內部事務回滾狀態的影響獨立提交或者回滾。

Supports:支援當前事務,使用PROPAGATION_SUPPORTS指定,指如果當前存在邏輯事務,就加入到該邏輯事務,如果當前沒有邏輯事務,就以非事務方式執行。

NotSupported:不支援事務,如果當前存在事務則暫停該事務,使用PROPAGATION_NOT_SUPPORTED指定,即以非事務方式執行,如果當前存在邏輯事務,就把當前事務暫停,以非事務方式執行。

Mandatory:使用PROPAGATION_MANDATORY指定,如果當前有事務,使用當前事務執行,如果當前沒有事務,則丟擲異常(IllegalTransactionStateException)。

Never:不支援事務,如果當前存在是事務則丟擲IllegalTransactionStateException異常,使用PROPAGATION_NEVER指定。

Nested:巢狀事務支援,使用PROPAGATION_NESTED指定,如果當前存在事務,則在巢狀事務內執行,如果當前不存在事務,則建立一個新的事務,巢狀事務使用資料庫中的儲存點來實現,即巢狀事務回滾不影響外部事務,但外部事務回滾將導致巢狀事務回滾

Nested和RequiresNew的區別: 
  • RequiresNew每次都建立新的獨立的物理事務,而Nested只有一個物理事務;
  • Nested巢狀事務回滾或提交不會導致外部事務回滾或提交,但外部事務回滾將導致巢狀事務回滾,而 RequiresNew由於都是全新的事務,所以之間是無關聯的;
  • Nested使用JDBC 3的儲存點實現,即如果使用低版本驅動將導致不支援巢狀事務。

    實際應用中一般使用預設的事務傳播行為,偶爾會用到RequiresNew和Nested方式。


3、Spring的隔離級別

宣告式事務的第二個方面是隔離級別。隔離級別定義一個事務可能受其他併發事務活動活動影響的程度。另一種考慮一個事務的隔離級別的方式,是把它想象為那個事務對於事物處理資料的自私程度。

在一個典型的應用程式中,多個事務同時執行,經常會為了完成他們的工作而操作同一個資料。併發雖然是必需的,但是會導致一下問題:

丟失更新   : 當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,會發生丟失更新問題。每個事務都不知道其它事務的存在。最後的更新將重寫由其它事務所做的更新,這將導致資料丟失。   :事務A和事務B同時修改某行的值,1.事務A將數值改為1並提交2.事務B將數值改為2並提交。這時資料的值為2,事務A所做的更新將會丟失。解決辦法:對行加鎖,只允許併發一個更新事務。

髒讀:

一個事務讀到另一個事務未提交的更新資料

:

1.Mary的原工資為1000, 財務人員將Mary的工資改為了8000(但未提交事務)         2.Mary讀取自己的工資 ,發現自己的工資變為了8000,歡天喜地!3.而財務發現操作有誤,回滾了事務,Mary的工資又變為了1000, 像這樣,Mary記取的工資數8000是一個髒資料。

不可重複讀:

在同一個事務中,多次讀取同一資料,返回的結果有所不同換句話說就是,後續讀取可以讀到另一個事務已提交的更新資料相反"可重複讀"在同一事務多次讀取資料時,能夠保證所讀資料一樣,也就是後續讀取不能讀到另一事務已提交的更新資料.

:

1.在事務1中,Mary 讀取了自己的工資為1000,操作並沒有完成2.在事務2中,這時財務人員修改了Mary的工資為2000,並提交了事務.3.在事務1中,Mary 再次讀取自己的工資時,工資變為了2000解決辦法:如果只有在修改事務完全提交之後才可以讀取資料,則可以避免該問題。

幻讀:

一個事務讀取到另一個事務已提交的insert資料.

:

第一個事務對一個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時 (此時第一事務還未提交,第二個事務向表中插入一行新資料。這時第一個事務再去讀取表時,發現表中還有沒有修改的資料行,就好象發生了幻覺一樣。

在理想狀態下,事務之間將完全隔離,從而可以防止這些問題發生。然而,完全隔離會影響效能,因為隔離經常牽扯到鎖定在資料庫中的記錄(而且有時是鎖定完整的資料表)。侵佔性的鎖定會阻礙併發,要求事務相互等待來完成工作。

考慮到完全隔離會影響效能,而且並不是所有應用程式都要求完全隔離,所以有時可以在事務隔離方面靈活處理。因此,就會有好幾個隔離級別。


隔離級別

含義

ISOLATION_DEFAULT

使用後端資料庫預設的隔離級別。

ISOLATION_READ_UNCOMMITTED

允許讀取尚未提交的更改。可能導致髒讀、幻影讀或不可重複讀。

ISOLATION_READ_COMMITTED

允許從已經提交的併發事務讀取。可防止髒讀,但幻影讀和不可重複讀仍可能會發生。

ISOLATION_REPEATABLE_READ

對相同欄位的多次讀取的結果是一致的,除非資料被當前事務本身改變。可防止髒讀和不可重複讀,但幻影讀仍可能發生。

ISOLATION_SERIALIZABLE

完全服從ACID的隔離級別,確保不發生髒讀、不可重複讀和幻影讀。這在所有隔離級別中也是最慢的,因為它通常是通過完全鎖定當前事務所涉及的資料表來完成的。

詳細解釋如下:

 1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager預設的隔離級別,使用資料庫預設的事務隔離級別.
      另外四個與JDBC的隔離級別相對應
 2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的資料。
      這種隔離級別會產生髒讀,不可重複讀和幻像讀。
 3. ISOLATION_READ_COMMITTED: 保證一個事務修改的資料提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的資料
 4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。
      它除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了避免下面的情況產生(不可重複讀)。
 5. ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
      除了防止髒讀,不可重複讀外,還避免了幻像讀。