Spring事務管理

事務的四大特性

原子性

:事務中的所有操作都是不可分割的原子單位。事務中的所有操作要麼全部執行成功,要麼全部執行失敗。

一致性

:事務執行後,資料庫狀態與其他與其他業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的。

隔離性

:隔離性是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾。

永續性

:一旦事務提交成功,事務中所有的資料操作都必須被持久化到資料庫中,即使提交事務後,資料庫馬上崩潰,在資料庫重啟時,也必須能保證透過某種機制恢復資料。

事務出現的問題

髒讀

(dirty read):一個事務讀取到另外一個事務中未提交的更新資料,即讀取到了髒資料。

不可重複讀

(unrepeatable read):對同一記錄的兩次讀取不一致,因為另一事務對該記錄做了修改。

幻讀

(phantom read):又稱虛讀,事務在兩次查詢返回的資料中發生了資料的缺少或增加,因為另一事務插入或刪除了一條記錄。

事務四大隔離級別

SERIALIZABLE

(序列化):

不會出現任何問題,因為它是對同一資料的訪問時序列的,非併發訪問!

效能最差!

REPEATABLE READ

(可重複讀):

防止髒讀和不可重複讀,不能處理幻讀問題!

效能較SERIALIZABLE好。

READ COMMITTED

(讀已提交資料):

防止髒讀,沒有處理不可重複讀和幻讀;

效能較前兩種更佳。

READ UNCOMMITTED

(讀未提交資料):

可能出現上述所有的事務併發問題;

效能在四種隔離中最優!

MySQL的預設隔離級別為

REPEATABLE READ

!Oracle的預設隔離級別為

READ COMMITTED

事務七種傳播行為

事務傳播行為(propagation behavior)指的就是當一個事務方法被另一個事務方法呼叫時,這個事務方法應該如何進行。 例如:methodA事務方法呼叫methodB事務方法時,methodB是繼續在呼叫者methodA的事務中執行呢,還是為自己開啟一個新事務執行,這就是由methodB的事務傳播行為決定的。

PROPAGATION_REQUIRED

:如果當前沒有事務,就建立一個新事務,如果當前存在事務,就加入該事務,該設定是最常用的設定。

PROPAGATION_SUPPORTS

:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行

PROPAGATION_MANDATORY

:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就丟擲異常。

PROPAGATION_REQUIRES_NEW

:建立新事務,無論當前存不存在事務,都建立新事務。

PROPAGATION_NOT_SUPPORTED

:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

PROPAGATION_NEVER

:以非事務方式執行,如果當前存在事務,則丟擲異常。

PROPAGATION_NESTED

:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則按 REQUIRED 屬性執行

Spring事務分類

宣告式事務

Spring 的宣告式事務管理是建立在 Spring AOP 機制之上的,其本質是對目標方法前後進行攔截,並在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。

簡單地說,宣告式事務是程式設計式事務 + AOP 技術包裝,使用註解進行掃包,指定範圍進行事務管理。宣告式事務管理要優於程式設計式事務管理,這正是 Spring 倡導的非侵入式的開發方式。

示例:

@Transactionalpublic void test3() // TODO 業務程式碼 }

程式設計式事務

在 Spring 出現以前,程式設計式事務管理對基於 POJO 的應用來說是唯一選擇。我們需要在程式碼中顯式呼叫 beginTransaction()、commit()、rollback() 等事務管理相關的方法,這就是程式設計式事務管理。

簡單地說,程式設計式事務就是在程式碼中顯式呼叫開啟事務、提交事務、回滾事務的相關方法,因此程式碼侵入性較大。

示例:

@Autowiredprivate PlatformTransactionManager transactionManager;public void test3() { TransactionStatus transactionStatus = this。transactionManager。getTransaction(new DefaultTransactionDefinition()); try { // TODO 業務程式碼 // 提交事務 this。transactionManager。commit(transactionStatus); } catch (Exception e) { // 回滾事務 this。transactionManager。rollback(transactionStatus); }}

Spring 事務的原理是使用 AOP 環繞通知 和 異常通知。

注意:在使用 Spring 事務時不能使用 try-catch 進行異常捕獲,要將異常拋給外層,使其進行異常攔截,觸發事務機制。否則導致事務失效,參考下篇Spring事務失效原因彙總

Spring事務三大介面

PlatformTransactionManager

事務管理器

TransactionDefinition

事務定義資訊(事務隔離級別、傳播行為、超時、只讀、回滾規則)

TransactionStatus

事務的一些狀態資訊,如是否一個新的事務、是否已被標記為回滾

1:事務管理器PlatformTransactionManager

真正用來管理事務的介面,包含 事務的提交,回滾等資訊。Spring 為不同的持久層框架 提供了 不同的實現類。然後根據不同的持久層框架 去選擇不同的 平臺事務管理器實現類。如果持久層框架使用jdbc,就選擇實現類

DataSourceTransactionManager。如果持久層使用Hibernate,就選擇實現類HibernateTransactionManager。

public interface PlatformTransactionManager extends TransactionManager { //根據事務定義TransactionDefinition,獲取事務 TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; //提交事務 void commit(TransactionStatus status) throws TransactionException; // 回滾事務 void rollback(TransactionStatus status) throws TransactionException; }

2:事務定義介面TransactionDefinition

事務的定義包括: 事務的隔離級別,事務的傳播屬性,超時時間設定,是否只讀。

事務的隔離級別是資料庫本身的事務功能,事務的傳播屬性則是spring為我們提供的功能,該介面的實現

DefaultTransactionDefinition,預設的事務定義:

1。事務的傳播屬性為PROPAGATION_REQUIRED,即當前沒有事務的時候,建立一個,如果有則使用當前事務

2。事務的隔離級別採用底層資料庫預設的隔離級別

3。超時時間採用底層資料庫預設的超時時間

4。是否只讀為false

public class DefaultTransactionDefinition implements TransactionDefinition, Serializable { private int propagationBehavior = PROPAGATION_REQUIRED; private int isolationLevel = ISOLATION_DEFAULT; private int timeout = TIMEOUT_DEFAULT; private boolean readOnly = false; //略}

3:事務執行狀態TransactionStatus

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable { /** * 是否有儲存點 */ boolean hasSavepoint(); void flush();}

TransactionStatus它繼承了SavepointManager介面,SavepointManager是對事務中上述儲存點功能的封裝,如下:

public interface SavepointManager { // 建立一個儲存點 Object createSavepoint() throws TransactionException; // 釋放一個儲存點 void releaseSavepoint(Object savepoint) throws TransactionException; // 回滾一個儲存點 void rollbackToSavepoint(Object savepoint) throws TransactionException;}

TransactionStatus本身更多儲存的是事務的一些狀態資訊:

Spring事務管理

是否是一個新的事物

是否有儲存點

是否已被標記為回滾

事務的五種狀態

1. 活動狀態

事務在執行時的狀態叫活動狀態。

2. 部分提交狀態

事務中最後一條語句被執行後的狀態叫部分提交狀態。

3. 失敗狀態

事務不能正常執行的狀態叫失敗狀態。

4. 提交狀態

事務在部分提交後,將往硬碟上寫入資料,當最後一條資訊寫入後的狀態叫提交狀態。進入提交狀態的事務就成功完成了。

5. 中止狀態

事務回滾並且資料庫已經恢復到事務開始執行前的狀態叫中止狀態。