一、事務的傳播特性
REQUIRED:默認的傳播特性,業務方法需要在一個事務中運行,如果一個方法已經處在一個事務中那么就加入到這個事務中,否則就會創建一個事務。
NEVER:指定的業務方法絕對不能在事務范圍內運行,如果業務方法在某個事務中執行,就會拋異常,只有業務方法沒有任何事務才正常執行。
MANDATORY:該屬性指定業務方法只能在一個已經存在的事務中執行,業務方法不能自己發起自己的事務,如果業務方法不存在事務,容器就拋異常。
SUPPORTS:如果業務方法中已經在某個事務中被調用,則方法就稱為事務的一部分,如果外部業務方法沒有開啟事務,supports該方法也會在沒有事務的環境中執行。
在沒有事務的環境下運行
NOT_SUPPORTED:如果該業務方法在一個事務中被調用,那么當前的事務會被掛起,執行該業務方法,方法執行完畢喚醒被掛起的事務,如果業務方法不在一個事務中執行,該方法也不會開事務。不管是否在有無事務的環境中執行都不開啟事務。
REQUIRES_NEW:不管是否存在事務,業務方法總會自己開啟一個事務,如果在已有事務的環境中調用,已有事務會被掛起,新的事務會被創建,直到業務方法調用結束,已有事務才被喚醒
NESTED:如果業務方法在一個事務中執行,就在這個事務中嵌套,如果沒有事務按着required執行,開啟單獨的事務,這種事務有多個事務的保存點,內部事務的回滾對外部事務沒有影響
二、事務的並發
並發問題:
問題1:臟讀(dirty read)
A事務讀到B事務沒有提交的數據,並且A來修改這個數據,如果恰巧B做事務回滾,那么A事務讀到的數據就是錯誤的
| 時間 |
轉賬事務A |
取款事務B |
| T1 |
|
開啟事務 |
| T2 |
開啟事務 |
|
| T3 |
|
查詢余額1000元 |
| T4 |
|
取500,剩500 |
| T5 |
查詢賬戶剩500(臟讀) |
|
| T6 |
|
撤銷了取款把余額恢復到1000 |
| T7 |
匯入100,余額變成600 |
|
| T8 |
提交事務 |
問題2:不可重復讀(unrepeatable read)
指的是A事務讀取了B事務已經提交了的更改數據,假設A取款的過程中B向賬戶匯入100,A事務兩次讀取數據不一致
| 時間 |
轉賬事務A |
取款事務B |
| T1 |
|
開啟事務 |
| T2 |
開啟事務 |
|
| T3 |
|
查詢余額1000元 |
| T4 |
查詢余額1000元 |
|
| T5 |
|
取出100,余額900 |
| T6 |
|
事務的提交 |
| T7 |
查詢余額900元(和T4一樣) |
|
| T8 |
提交事務 |
問題3:幻讀(phantom read)
A事務讀取B事務新增的數據,假設銀行做在一個A事務中統計,在統計過程中B新增了用戶,A的事務中兩次統計不同
| 時間 |
統計金額A |
開戶事務B |
| T1 |
|
開啟事務 |
| T2 |
開啟事務 |
|
| T3 |
統計為10000 |
|
| T4 |
|
新增用戶,並且存入100 |
| T5 |
|
|
| T6 |
|
事務的提交 |
| T7 |
統計為10100 |
|
| T8 |
提交事務 |
問題4:第一類更新丟失
| 時間 |
轉賬事務A |
取款事務B |
| T1 |
|
開啟事務 |
| T2 |
開啟事務 |
|
| T3 |
|
查詢余額1000元 |
| T4 |
查詢余額1000元 |
|
| T5 |
匯入100,余額變1100 |
|
| T6 |
提交 |
|
| T7 |
|
取出100,余額變成900 |
| T8 |
|
撤銷事務 |
| T9 |
|
余額要恢復1000(更新丟失) |
問題5:第二類更新丟失
| 時間 |
轉賬事務A |
取款事務B |
| T1 |
|
開啟事務 |
| T2 |
開啟事務 |
|
| T3 |
|
查詢余額1000元 |
| T4 |
查詢余額1000元 |
|
| T5 |
|
取100,余額900 |
| T6 |
|
提交 |
| T7 |
匯入100,余額變1100 |
|
| T8 |
提交事務 |
|
| T9 |
余額變1100(丟失更新) |
| 隔離級別 |
臟讀 |
不可重復讀 |
幻讀 |
第一丟失更新 |
第二丟失更新 |
| READ UNCOMMITED |
Y |
Y |
Y |
N |
Y |
| READ COMMITED |
N |
Y |
Y |
N |
Y |
| REPEATABLE READ |
N |
N |
Y |
N |
N |
| SERIALIZEABLE |
N |
N |
N |
N |
N |
