spring 事務傳播行為和事務隔離級別
1、Spring宣告式事務
宣告式事務(declarative transaction management)是Spring提供的對程式事務管理的方式之一。 Spring的宣告式事務顧名思義就是採用宣告的方式來處理事務。這裡所說的宣告,就是指在配置檔案中申明。用在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 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止髒讀,不可重複讀外,還避免了幻像讀。