先看下@Transactional可以配制那些參數及以其所代表的意義。
isolation |
枚舉org.springframework.transaction.annotation.Isolation的值 |
事務隔離級別 |
noRollbackFor |
Class<? extends Throwable>[] |
一組異常類,遇到時不回滾。默認為{} |
noRollbackForClassName |
Stirng[] |
一組異常類名,遇到時不回滾,默認為{} |
propagation |
枚舉org.springframework.transaction.annotation.Propagation的值 |
事務傳播行為 |
readOnly |
boolean |
事務讀寫性 |
rollbackFor |
Class<? extends Throwable>[] |
一組異常類,遇到時回滾 |
rollbackForClassName |
Stirng[] |
一組異常類名,遇到時回滾 |
timeout |
超時時間,以秒為單位 |
|
value |
String |
可選的限定描述符,指定使用的事務管理器 |
isolation事務隔離級別,使用時一般如下。
-
-
public void method(){}
isolation的參數有以下五種:
1_1、Isolation.DEFAULT:為數據源的默認隔離級別
1_2、isolation=Isolation.READ_UNCOMMITTED:未授權讀取級別
以操作同一行數據為前提,讀事務允許其他讀事務和寫事務,未提交的寫事務禁止其他寫事務(但允許其他讀事務)。此隔離級別可以防止更新丟失,但不能防止臟讀、不可重復讀、幻讀。此隔離級別可以通過“排他寫鎖”實現。
1_3、iIsolation.READ_COMMITTED:授權讀取級別
以操作同一行數據為前提,讀事務允許其他讀事務和寫事務,未提交的寫事務禁止其他讀事務和寫事務。此隔離級別可以防止更新丟失、臟讀,但不能防止不可重復讀、幻讀。此隔離級別可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。
1_4、iIsolation.REPEATABLE_READ:可重復讀取級別
以操作同一行數據為前提,讀事務禁止其他寫事務(但允許其他讀事務),未提交的寫事務禁止其他讀事務和寫事務。此隔離級別可以防止更新丟失、臟讀、不可重復讀,但不能防止幻讀。此隔離級別可以通過“共享讀鎖”和“排他寫鎖”實現。
1_5、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_COMMITTEDOracle 默認隔離級別 READ_COMMITTED