提示
事務傳播行為率先出現(xiàn)在 Spring 框架中,HasorDB 對其思想并未有什么改進而是在 HasorDB 中提供了一套完整的實現(xiàn)。
簡單的理解就是多個事務方法相互調用時,事務如何在這些方法間傳播。舉個例子:
?方法A
? 是一個事務的方法,在執(zhí)行過程中調用了 ?方法B
?。 接下來 ?方法B
? 有無事務以及 ?方法B
? 對事務的要求不同都會對 ?方法A
?的事務具體執(zhí)行造成影響。 同時 ?方法A
? 的事務對? 方法B
? 的事務執(zhí)行也有影響,這種影響具體是什么就由兩個方法所定義的事務傳播行為所決定。
Propagation.REQUIRED
?嘗試加入已經存在的事務中,如果沒有則開啟一個新的事務。
時間 | 事務1 | 事務2(REQUIRED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 什么都不做 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.REQUIRES_NEW
?將掛起當前存在的事務掛起(如果存在的話)并且開啟一個全新的事務,新事務與已存在的事務之間彼此沒有關系。
DataSourceManager
? 中正在使用的同步資源被臨時保存
DataSourceManager
?會得到一個全新的數據庫連接。
時間 | 事務1 | 事務2(REQUIRES_NEW) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 產生新的連接并且和當前線程綁定,以滿足 本地同步 | |
T4 | insert data2 | 在新連接上寫入 | |
T5 | commit/rollback | 操作新的 Connection
|
|
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.NESTED
?在當前事務中通過 ?Savepoint
? 方式開啟一個子事務。
時間 | 事務1 | 事務2(NESTED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 創(chuàng)建事務保存點 | |
T4 | insert data2 | ||
T5 | commit/rollback | commit 會釋放保存點、rollback 會回退到 T3 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.SUPPORTS
?如果當前沒有事務存在,就以非事務方式執(zhí)行;如果有,就使用當前事務。以下面的執(zhí)行為例:
SUPPORTS
?行為是事務傳播屬性中最簡單的一種行為,其行為本質上強調了 不作為
時間 | 事務1 | 事務2(SUPPORTS) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | ||
T4 | insert data2 | 注1 若 T1 開啟了事務,那么效果等同于 REQUIRED
|
|
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Connection
?對象的 ?autoCommit
?屬性為 ?false
?。
能夠導致啟動事務的傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,如果使用 低級別 API 手動改變 autoCommit 狀態(tài)也會導致進入事務狀態(tài)。Propagation.NOT_SUPPORTED
?如果當前沒有事務存在,就以非事務方式執(zhí)行;如果有,就將當前事務掛起。以下面的執(zhí)行為例:
注意
將掛起當前存在的事務掛起(如果存在的話)并且開啟一個全新的事務,新事務與已存在的事務之間彼此沒有關系。
- 掛起會導致 ?
DataSourceManager
?中正在使用的同步資源被臨時保存。
- 在掛起之后訪問 ?
DataSourceManager
?會得到一個全新的數據庫連接。
時間 | 事務1 | 事務2(NOT_SUPPORTED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 開啟了事務,那么會掛起當前事務。但不開啟新的事務 | |
T4 | insert data2 | ||
T5 | commit/rollback | 注2 若 T3 掛起了事務,那么會恢復它。 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Connection
?對象的 ?autoCommit
?屬性為 ?false
?。 能夠導致啟動事務的傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,如果使用 低級別 API 手動改變 ?autoCommit
?狀態(tài)也會導致進入事務狀態(tài)。DataSourceManager
?的當前綁定連接為之前的那一個。Propagation.NEVER
?如果當前沒有事務存在,就以非事務方式執(zhí)行;如果有就拋出異常。
時間 | 事務1 | 事務2(NEVER) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 開啟了事務,那么會拋出異常 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
NOT_SUPPORTED
? 那么 T3 環(huán)節(jié)上 ?NEVER
?行為就不會報錯。它的行為會和 ?SUPPORTS
?等價。 若 T1 這個動作導致了 ?Connection
?對象的 ?autoCommit
?屬性為 ?false
?那么 T3 環(huán)節(jié)就會報錯。autoCommit
?為 ?false
?傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,也可以通過使用 低級別 API 改變。Propagation.MANDATORY
?如果當前沒有事務存在,就拋出異常;如果有,就使用當前事務。
時間 | 事務1 | 事務2(NEVER) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 不存在事務,那么會拋出異常 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
MANDATORY
?是要求必須 T1 環(huán)節(jié)產生了一個事務,否則會報錯。 因此若 T1 環(huán)節(jié)使用的是? NOT_SUPPORTED
?行為,那么 T3 環(huán)節(jié)就會報錯。
更多建議: