1. 程式人生 > >SpringBoot事務詳解

SpringBoot事務詳解

一、定義

    事務(transaction)是指業務邏輯上對資料庫進行的一系列持久化操作,要麼全部成功,要麼全部失敗。

二、特性和實現

1、事務的四個基本性質(ACID)

    1)原子性(Atomicity)

          事務的原子性指事務是一個不可分割的工作單位,這組操作要麼全部執行,要麼全部不發生。

          就拿銀行轉賬來說,原子性指的是從A賬戶扣款和轉賬到B賬戶兩件事一起發生,不能只發生其中一樣。

   2)一致性(Consistency)

          在事務開始的前後,被操作的資料的完整性都處於一致性的狀態。

          還是銀行轉賬的例子,一致性指的是在轉賬的前後A和B兩個賬戶的總金額是不變的,始終保持一致。

    3)隔離性(Isolation)

          多個事務併發時,事務之間是隔離的,每個事務都有自己的完整資料空間,不會影響到其他事物的執行效果。

          事務隔離性的四種隔離級別和實現原理這裡就不作闡述,感興趣的可以看以下兩篇部落格:

                四種隔離級別      https://blog.csdn.net/qq_33290787/article/details/51924963

                實現原理            https://blog.csdn.net/matt8/article/details/53096405

    4)永續性(Durability)

          事務提交後,該事務對資料所做的修改將持久地儲存在資料庫,並不會回滾。

    事務的原子性、一致性和永續性是通過資料庫的redo/undo日誌檔案實現的。redo log處理系統故障,undo log處理事務回滾。如果在事務提交之後出現數據庫崩潰(斷電)的情況,在恢復供電時,資料庫會根據重寫日誌對資料進行前滾。

 2、事務的實現

    在Spring中,事務有兩種實現方式,分別是程式設計式事務和宣告式事務。

    程式設計式事務:程式設計式事務管理使用Transaction Template或者直接使用底層的Platform TransactionManager。對於程式設計式事務,Spring推薦使用Transaction Template。TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

    宣告式事務:宣告式事務基於AOP,其本質是對方法前後進行攔截,在方法開始前建立或加入一個事務,再根據目標方法執行的結果決定提交還是回滾事務。只需要在類、方法加上@Transactional註解就可以使用事務,沒有入侵性,簡單粗暴。

三、宣告式事務的使用技巧

1、@Transactional可以作用於介面、介面方法、類、類方法上,當作用到類時,該類下所有public方法都將具有該型別的事務屬性,同時,也可以在方法級別使用該註解來覆蓋類級別的定義。Spring的建議是在具體的實現類和類方法使用@Transactional註解,而不是使用在介面上。因為註解不能繼承,不能被基於介面的代理類所識別,註解失效。

    2、宣告式事務管理預設只對非檢查型異常unchecked Exception進行回滾,也就是對RuntimeException異常以及它的子類進行回滾操作。

    如果需要讓checked Exception也進行回滾,需加上@Transactional(rollbackFor=Exception.class)、

    如果需要讓unchecked Exception不進行回滾,需加上@Transactional(notRollbackFor=Exception.class)

    3、在Springboot使用宣告式事務需要在Application啟動類加入@EnableTransactionManagement註解,相當於Spring的自動掃描

四、宣告式事務的常用配置

參 數 名 稱 功 能 描 述
readOnly 該屬性用於設定當前事務是否為只讀事務,設定為true表示只讀,false則表示可讀寫,預設值為false。例如:@Transactional(readOnly=true)
rollbackFor 該屬性用於設定需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,則進行事務回滾。例如:指定單一異常類:@Transactional(rollbackFor=RuntimeException.class)指定多個異常類:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassName 該屬性用於設定需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,則進行事務回滾。例如:指定單一異常類名稱@Transactional(rollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})
noRollbackFor 該屬性用於設定不需要進行回滾的異常類陣列,當方法中丟擲指定異常陣列中的異常時,不進行事務回滾。例如:指定單一異常類:@Transactional(noRollbackFor=RuntimeException.class)指定多個異常類:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName 該屬性用於設定不需要進行回滾的異常類名稱陣列,當方法中丟擲指定異常名稱陣列中的異常時,不進行事務回滾。例如:指定單一異常類名稱:@Transactional(noRollbackForClassName=”RuntimeException”)指定多個異常類名稱:@Transactional(noRollbackForClassName={“RuntimeException”,”Exception”})
propagation 該屬性用於設定事務的傳播行為。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
isolation 該屬性用於設定底層資料庫的事務隔離級別,事務隔離級別用於處理多事務併發的情況,通常使用資料庫的預設隔離級別即可,基本不需要進行設定
timeout 該屬性用於設定事務的超時秒數,預設值為-1表示永不超時

五、宣告式事務的隔離級別

隔離級別是指若干個併發的事務之間的隔離程度。TransactionDefinition 介面中定義了五個表示隔離級別的常量:

TransactionDefinition.ISOLATION_DEFAULT:這是預設值,表示使用底層資料庫的預設隔離級別。對大部分資料庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。 
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的資料。該級別不能防止髒讀,不可重複讀和幻讀,因此很少使用該隔離級別。比如PostgreSQL實際上並沒有此級別。 
TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的資料。該級別可以防止髒讀,這也是大多數情況下的推薦值。 
TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程中可以多次重複執行某個查詢,並且每次返回的記錄都相同。該級別可以防止髒讀和不可重複讀。 
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。但是這將嚴重影響程式的效能。通常情況下也不會用到該級別。

六、宣告式事務的傳播行為

所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括瞭如下幾個表示傳播行為的常量:

TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則建立一個新的事務。這是預設值。 
TransactionDefinition.PROPAGATION_REQUIRES_NEW:建立一個新的事務,如果當前存在事務,則把當前事務掛起。 
TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。 
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式執行,如果當前存在事務,則把當前事務掛起。 
TransactionDefinition.PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則丟擲異常。 
TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則丟擲異常。 
TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則建立一個事務作為當前事務的巢狀事務來執行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。

參考部落格:

SpringBoot事務註解@Transactional    https://blog.csdn.net/wkl305268748/article/details/77619367

事務的四大特徵      https://blog.csdn.net/longxingzhiwen/article/details/53912475

理解事務的四種隔離級別     https://blog.csdn.net/qq_33290787/article/details/51924963 

@Transactional(rollbackFor=Exception.class)的使用  https://blog.csdn.net/Mint6/article/details/78363761