Spring事務的隔離級別和傳播行為
事務(Transaction)是訪問并可能更新資料庫中各種資料項的一個程式執行單元(unit),事務通常由高級資料庫操縱語言或編程語言(如SQL、C++或Java)書寫的用戶程式的執行所引起,并用形如begin transaction和end transaction陳述句(或函式呼叫)來界定,事務由事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操作組成,例如:在關系資料庫中,一個事務可以是一條SQL陳述句,一組SQL陳述句或整個程式,
事務是恢復和并發控制的基本單位,
事務隔離級別定義了在一個事務中,哪些資料是對當前執行的陳述句“可見”的,在并發訪問資料庫時,事務隔離級別定義了多個事務之間對于同個目標資料源訪問時的可交叉程度,
一、可交叉程度
1??Dirty Read(臟讀) 看到的資料則是不正確的
當一個事務能看見另外一個事務未提交的資料時,就稱為臟讀,如果這個事務被回滾了而不是提交了,那么其它事務看到的資料則是不正確的,是“臟”的,

2??Non-repeatable Read(不可重復讀) 兩次讀取到的資料不同
假設事務A讀取了一行資料,接下來事務B改變了這行資料,之后事務A再一次讀取這行資料,結果就是事務A兩次讀取到的資料不同,

3??Phantom Read(幻讀) 發現多出來一條資料
假設事務A通過一個 where 條件讀取到了一個結果集,事務B這時插入了一條符合事務A的 where 條件的資料,之后事務A通過同樣的 where 條件再次查詢時,發現多出來一條資料,

二、事務隔離級別(Isolation)
JDBC 規范增加了隔離級別,來滿足了 SQL:2003 定義的 4 種事務隔離級別,在安裝MySQL時,安裝默認的隔離級別就是:可重復讀,可以通過 select @@global.tx_isolation; 來查看當前隔離級別,隔離級別從最寬松到最嚴格,排序如下所示:
1??TRANSACTION_NONE
這意味著當前的 JDBC 驅動不支持事務,也意味著這個驅動不符合 JDBC 規范,
2??READ_UNCOMMITTED(讀未提交)
允許事務看到其它事務修改了但未提交的資料,這意味著有可能是臟讀、不可重復讀或者幻讀,
3??READ_COMMITTED(讀提交)
一個事務在未提交之前,所做的修改不會被其它事務所看見,這能避免臟讀,但避免不了不可重復讀和幻讀,
4??REPEATABLE_READ(可重復讀取) MySQL默認的事務隔離級別
避免了臟讀和不可重復讀,但幻讀依然是有可能發生的,
5??SERIALIZABLE(序列化)
避免了臟讀、不可重復讀以及幻讀,

三、Propagation事務傳播行為
Propagation屬性用來列舉事務的傳播行為,所謂事務傳播行為就是多個事務方法相互呼叫時,事務如何在這些方法間傳播,Spring支持7種事務傳播行為,默認為REQUIRED,
1??REQUIRED
REQUIRED是常用的事務傳播行為,如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中,
2??SUPPORTS
SUPPORTS表示當前方法不需要事務背景關系,但是如果存在當前事務的話,那么這個方法會在這個事務中運行,
3??MANDATORY
MANDATORY表示該方法必須在事務中運行,如果當前事務不存在,則會拋出一個例外,不會主動開啟一個事務,
4??REQUIRES_NEW
REQUIRES_NEW表示當前方法必須運行在它自己的事務中,一個新的事務將被啟動,如果存在當前事務,在該方法執行期間,當前事務會被掛起(如果一個事務已經存在,則先將這個存在的事務掛起),如果使用JTATransactionManager的話,則需要訪問TransactionManager,
5??NOT_SUPPORTED
NOT_SUPPORTED表示該方法不應該運行在事務中,如果存在當前事務,在該方法運行期間,當前事務將被掛起,如果使用JTATransactionManager的話,則需要訪問TransactionManager,
6??NEVER
NEVER表示當前方法不應該運行在事務背景關系中,如果當前正有一個事務在運行,則會拋出例外,
7??NESTED
NESTED表示如果當前已經存在一個事務,那么該方法將會在嵌套事務中運行,嵌套的事務可以獨立于當前事務進行單獨地提交或回滾,如果當前事務不存在,那么其行為與REQUIRED一樣,嵌套事務一個非常重要的概念就是內層事務依賴于外層事務,外層事務失敗時,會回滾內層事務所做的動作,而內層事務操作失敗并不會引起外層事務的回滾,
綜上所述,NESTED和REQUIRES_NEW非常相似,都是開啟一個屬于它自己的新事務,使用REQUIRES_NEW時,內層事務與外層事務就像兩個獨立的事務一樣,一旦內層事務進行了提交后,外層事務不能對其進行回滾,當內部事務開始執行時, 外部事務將被掛起, 內務事務結束時, 外部事務將繼續執行,兩個事務互不影響,兩個事務不是一個真正的嵌套事務,同時它還需要JTA事務管理器的支持,
使用NESTED時,外層事務的回滾可以引起內層事務的回滾,而內層事務的例外并不會導致外層事務的回滾,它是一個真正的嵌套事務,嵌套事務開始執行時, 它將取得一個 savepoint,如果這個嵌套事務失敗, 將回滾到此savepoint,潛套事務是外部事務的一部分, 只有外部事務結束后它才會被提交,
四、Spring事務的基本原理
Spring事務的本質其實就是資料庫對事務的支持,沒有資料庫的事務支持,Spring是無法提供事務功能的,對于純JDBC操作資料庫,想要用到事務,可以按照以下步驟進行:
- 獲取連接 Connection con = DriverManager.getConnection();
- 開啟事務 con.setAutoCommit(true/false);
- 執行 CRUD;
- 提交事務/回滾事務 con.commit()/con.rollback();
- 關閉連接 con.close(),
使用Spring的事務管理功能后,程式員可以不再寫步驟 2 和 4 的代碼,而是由 Spirng 自動完成,Spring是如何CRUD之前和之后開啟事務和關閉事務的?解決這個問題,也就可以從整體上理解Spring的事務管理實作原理了,下面簡單地介紹下,注解方式為例子:
- 組態檔開啟注解驅動,在相關的類和方法上通過注解@Transactional標識,
- Spring 在啟動的時候會去決議生成相關的bean,這時候會查看擁有相關注解的類和方法,并且為這些類和方法生成代理,并根據@Transactional的相關引數進行相關配置注入,這樣就在代理中把相關的事務實作了(開啟正常提交事務,例外回滾事務),
- 真正的資料庫層的事務提交和回滾是通過binlog或者redo log實作的,
五、原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)
事務最經典的例子就是轉賬了,假如小明要給小紅轉賬100元,這個轉賬會涉及到兩個關鍵操作就是:將小明的余額減少100元,將小紅的余額增加100元,萬一在這兩個操作之間突然出現錯誤(如銀行系統崩潰等),導致小明余額減少而小紅的余額沒有增加,這樣就不對了,事務就是保證這兩個關鍵操作要么都成功,要么都要失敗,

1??原子性(atomicity),一個事務是一個不可分割的作業單位,事務中包括的操作要么都做,要么都不做,
2??一致性(consistency),事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態,一致性與原子性是密切相關的,
3??隔離性(isolation),一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對并發的其他事務是隔離的,并發執行的各個事務之間不能互相干擾,
4??持久性(durability),持久性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的,接下來的其他操作或故障不應該對其有任何影響,
(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的,接下來的其他操作或故障不應該對其有任何影響,
轉載自:原文鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/265304.html
標籤:其他
上一篇:專案總結
