事務(Transaction)是訪問並可能更新數據庫中各類數據項的一個程序執行單元(unit)。事務一般由高級數據庫操縱語言或編程語言(如SQL、C++或Java)書寫的用戶程序的執行所引發,並用形如begin transaction和end transaction語句(或函數調用)來界定。事務由事務開始(begin transaction)和事務結束(end transaction)之間執行的全體操做組成。例如:在關係數據庫中,一個事務能夠是一條SQL語句,一組SQL語句或整個程序。程序員
事務是恢復和併發控制的基本單位。
事務隔離級別定義了在一個事務中,哪些數據是對當前執行的語句「可見」的。在併發訪問數據庫時,事務隔離級別定義了多個事務之間對於同個目標數據源訪問時的可交叉程度。spring
1️⃣Dirty Read(髒讀) 看到的數據則是不正確的
數據庫
當一個事務能看見另一個事務未提交的數據時,就稱爲髒讀。若是這個事務被回滾了而不是提交了,那麼其它事務看到的數據則是不正確的,是「髒」的。編程
2️⃣Non-repeatable Read(不可重複讀) 兩次讀取到的數據不一樣
併發
假設事務A讀取了一行數據,接下來事務B改變了這行數據,以後事務A再一次讀取這行數據,結果就是事務A兩次讀取到的數據不一樣。編程語言
3️⃣Phantom Read(幻讀) 發現多出來一條數據
函數
假設事務A經過一個 where 條件讀取到了一個結果集,事務B這時插入了一條符合事務A的 where 條件的數據,以後事務A經過一樣的 where 條件再次查詢時,發現多出來一條數據。atom
JDBC 規範增長了隔離級別,來知足了 SQL:2003 定義的 4 種事務隔離級別。在安裝MySQL時,安裝默認的隔離級別就是:可重複讀。
能夠經過 select @@global.tx_isolation;
來查看當前隔離級別。隔離級別從最寬鬆到最嚴格,排序以下所示:代理
1️⃣TRANSACTION_NONE
這意味着當前的 JDBC 驅動不支持事務,也意味着這個驅動不符合 JDBC 規範。code
2️⃣READ_UNCOMMITTED(讀未提交)
容許事務看到其它事務修改了但未提交的數據,這意味着有多是髒讀、不可重複讀或者幻讀。
3️⃣READ_COMMITTED(讀提交)
一個事務在未提交以前,所作的修改不會被其它事務所看見。這能避免髒讀,但避免不了不可重複讀和幻讀。
4️⃣REPEATABLE_READ(可重複讀取) MySQL默認的事務隔離級別
避免了髒讀和不可重複讀,但幻讀依然是有可能發生的。
5️⃣SERIALIZABLE(序列化)
避免了髒讀、不可重複讀以及幻讀。
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是沒法提供事務功能的。對於純JDBC操做數據庫,想要用到事務,能夠按照如下步驟進行:
使用Spring的事務管理功能後,程序員能夠再也不寫步驟 2 和 4 的代碼,而是由 Spirng 自動完成。Spring是如何CRUD以前和以後開啓事務和關閉事務的?解決這個問題,也就能夠從總體上理解Spring的事務管理實現原理了。下面簡單地介紹下,註解方式爲例子:
事務最經典的例子就是轉帳了。假如小明要給小紅轉帳100元,這個轉帳會涉及到兩個關鍵操做就是:將小明的餘額減小100元,將小紅的餘額增長100元。萬一在這兩個操做之間忽然出現錯誤(如銀行系統崩潰等),致使小明餘額減小而小紅的餘額沒有增長,這樣就不對了。事務就是保證這兩個關鍵操做要麼都成功,要麼都要失敗。
1️⃣原子性(atomicity)。一個事務是一個不可分割的工做單位,事務中包括的操做要麼都作,要麼都不作。
2️⃣一致性(consistency)。事務必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的。
3️⃣隔離性(isolation)。一個事務的執行不能被其餘事務干擾。即一個事務內部的操做及使用的數據對併發的其餘事務是隔離的,併發執行的各個事務之間不能互相干擾。
4️⃣持久性(durability)。持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其餘操做或故障不該該對其有任何影響。
(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其餘操做或故障不該該對其有任何影響。
轉載自:原文連接