Spring事物隔離級別及事物傳播行爲@Transactional實現

閱讀本篇文章前,請先閱讀以下文章:html

四種事物隔離級別詳解

 

先看下@Transactional能夠配製那些參數及以其所表明的意義。spring

isolation數據庫

枚舉org.springframework.transaction.annotation.Isolation的值併發

事務隔離級別post

noRollbackFor性能

Class<? extends Throwable>[]url

一組異常類,遇到時不回滾。默認爲{}spa

noRollbackForClassNamehtm

Stirng[]blog

一組異常類名,遇到時不回滾,默認爲{}

propagation

枚舉org.springframework.transaction.annotation.Propagation的值

事務傳播行爲

readOnly

boolean

事務讀寫性

rollbackFor

Class<? extends Throwable>[]

一組異常類,遇到時回滾

rollbackForClassName

Stirng[]

一組異常類名,遇到時回滾

timeout

 

超時時間,以秒爲單位

value

String

可選的限定描述符,指定使用的事務管理器

 


isolation事務隔離級別,使用時通常以下。

@Transactional(isolation=Isolation.DEFAULT)

public void method(){}

 

isolation的參數有如下五種:

1_一、Isolation.DEFAULT:爲數據源的默認隔離級別

1_二、isolation=Isolation.READ_UNCOMMITTED:未受權讀取級別

以操做同一行數據爲前提,讀事務容許其餘讀事務和寫事務,未提交的寫事務禁止其餘寫事務(但容許其餘讀事務)。此隔離級別能夠防止更新丟失,但不能防止髒讀、不可重複讀、幻讀。此隔離級別能夠經過「排他寫鎖」實現。

1_三、iIsolation.READ_COMMITTED:受權讀取級別

以操做同一行數據爲前提,讀事務容許其餘讀事務和寫事務,未提交的寫事務禁止其餘讀事務和寫事務。此隔離級別能夠防止更新丟失、髒讀,但不能防止不可重複讀、幻讀。此隔離級別能夠經過「瞬間共享讀鎖」和「排他寫鎖」實現。

1_四、iIsolation.REPEATABLE_READ:可重複讀取級別

以操做同一行數據爲前提,讀事務禁止其餘寫事務(但容許其餘讀事務),未提交的寫事務禁止其餘讀事務和寫事務。此隔離級別能夠防止更新丟失、髒讀、不可重複讀,但不能防止幻讀。此隔離級別能夠經過「共享讀鎖」和「排他寫鎖」實現。

1_五、iIsolation.SERIALIZABLE:序列化級別

提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,不能併發執行。此隔離級別能夠防止更新丟失、髒讀、不可重複讀、幻讀。若是僅僅經過「行級鎖」是沒法實現事務序列化的,必須經過其餘機制保證新插入的數據不會被剛執行查詢操做的事務訪問到。

隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也越大。對於多數應用程序,能夠優先考慮把數據庫系統的隔離級別設爲Read Committed。它可以避免更新丟失、髒讀,並且具備較好的併發性能。儘管它會致使不可重複讀、幻讀這些併發問題,在可能出現這類問題的個別場合,能夠由應用程序採用悲觀鎖或樂觀鎖來控制。

有關事務的關鍵字說明以下,說明以下:

 

原子性(Atomicity):

事務是數據庫的邏輯工做單位,它對數據庫的修改要麼所有執行,要麼所有不執行。

一致性(Consistemcy):

事務先後,數據庫的狀態都知足全部的完整性約束。

隔離性(Isolation):

併發執行的事務是隔離的,一個不影響一個。若是有兩個事務,運行在相同的時間內,執行相同的功能,事務的隔離性將確保每一事務在系統中認爲只有該事務在使用系統。這種屬性有時稱爲串行化,爲了防止事務操做間的混淆,必須串行化或序列化請求,使得在同一時間僅有一個請求用於同一數據。經過設置數據庫的隔離級別,能夠達到不一樣的隔離效果。

持久性(Durability):

在事務完成之後,該事務所對數據庫所做的更改便持久的保存在數據庫之中,並不會被回滾。

更新丟失:

兩個事務都同時更新一行數據,可是第二個事務卻中途失敗退出,致使對數據的兩個修改都失效了。這是由於系統沒有執行任何的鎖操做,所以併發事務並無被隔離開來。

髒讀:

髒讀又稱無效數據讀出。一個事務讀取另一個事務尚未提交的數據叫髒讀。

例如:事務T1修改了一行數據,可是尚未提交,這時候事務T2讀取了被事務T1修改後的數據,以後事務T1由於某種緣由Rollback了,那麼事務T2讀取的數據就是髒的。

不可重複讀:

不可重複讀是指在同一個事務內,兩個相同的查詢返回了不一樣的結果。

例如:事務T1讀取某一數據,事務T2讀取並修改了該數據,T1爲了對讀取值進行檢驗而再次讀取該數據,便獲得了不一樣的結果。

幻讀:

事務在操做過程當中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據或者缺乏了第一次查詢中出現的數據

例如:系統管理員A將數據庫中全部學生的成績從具體分數改成ABCDE等級,可是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺同樣。這就叫幻讀。

以上的4種問題(更新丟失、髒讀、不可重複讀、幻讀)都和事務的隔離級別有關。經過設置事務的隔離級別,能夠避免上述問題的發生。

事物傳播行爲介紹:

  @Transactional(propagation=Propagation.REQUIRED) :若是有事務, 那麼加入事務, 沒有的話新建一個(默認狀況下)
  @Transactional(propagation=Propagation.NOT_SUPPORTED) :容器不爲這個方法開啓事務
  @Transactional(propagation=Propagation.REQUIRES_NEW) :不論是否存在事務,都建立一個新的事務,原來的掛起,新的執行完畢,繼續執行老的事務
  @Transactional(propagation=Propagation.MANDATORY) :必須在一個已有的事務中執行,不然拋出異常
  @Transactional(propagation=Propagation.NEVER) :必須在一個沒有的事務中執行,不然拋出異常(與Propagation.MANDATORY相反)
  @Transactional(propagation=Propagation.SUPPORTS) :若是其餘bean調用這個方法,在其餘bean中聲明事務,那就用事務.若是其餘bean沒有聲明事務,那就不用事務.

 

事物超時設置:

  @Transactional(timeout=30) //默認是30秒

 

事務隔離級別:

  @Transactional(isolation = Isolation.READ_UNCOMMITTED):讀取未提交數據(會出現髒讀, 不可重複讀) 基本不使用
  @Transactional(isolation = Isolation.READ_COMMITTED):讀取已提交數據(會出現不可重複讀和幻讀)
  @Transactional(isolation = Isolation.REPEATABLE_READ):可重複讀(會出現幻讀)
  @Transactional(isolation = Isolation.SERIALIZABLE):串行化

  MYSQL: 默認爲REPEATABLE_READ級別

  SQLSERVER: 默認爲READ_COMMITTED

  Oracle 默認隔離級別 READ_COMMITTED

相關文章
相關標籤/搜索