spring事務:
什麼是事務:
事務邏輯上的一組操做,組成這組操做的各個邏輯單元,要麼一塊兒成功,要麼一塊兒失敗.spring
事務特性(4種):
原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執行的先後數據的完整性保持一致.
隔離性 (isolation):一個事務執行的過程當中,不該該受到其餘事務的干擾
持久性(durability) :事務一旦結束,數據就持久到數據庫sql
若是不考慮隔離性引起安全性問題:
髒讀 :一個事務讀到了另外一個事務的未提交的數據
不可重複讀 :一個事務讀到了另外一個事務已經提交的 update 的數據致使屢次查詢結果不一致.
虛幻讀 :一個事務讀到了另外一個事務已經提交的 insert 的數據致使屢次查詢結果不一致.數據庫
解決讀問題: 設置事務隔離級別(5種)
DEFAULT 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.
未提交讀(read uncommited) :髒讀,不可重複讀,虛讀都有可能發生
已提交讀 (read commited):避免髒讀。可是不可重複讀和虛讀有可能發生
可重複讀 (repeatable read) :避免髒讀和不可重複讀.可是虛讀有可能發生.
串行化的 (serializable) :避免以上全部讀問題.
Mysql 默認:可重複讀
Oracle 默認:讀已提交安全
read uncommited:是最低的事務隔離級別,它容許另一個事務能夠看到這個事務未提交的數據。
read commited:保證一個事物提交後才能被另一個事務讀取。另一個事務不能讀取該事物未提交的數據。
repeatable read:這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能會出現幻象讀。它除了保證一個事務不能被另一個事務讀取未提交的數據以外還避免瞭如下狀況產生(不可重複讀)。
serializable:這是花費最高代價但最可靠的事務隔離級別。事務被處理爲順序執行。除了防止髒讀,不可重複讀以外,還避免了幻象讀(避免三種)。atom
事務的傳播行爲
PROPAGION_XXX :事務的傳播行爲
* 保證同一個事務中
PROPAGATION_REQUIRED 支持當前事務,若是不存在 就新建一個(默認)
PROPAGATION_SUPPORTS 支持當前事務,若是不存在,就不使用事務
PROPAGATION_MANDATORY 支持當前事務,若是不存在,拋出異常
* 保證沒有在同一個事務中
PROPAGATION_REQUIRES_NEW 若是有事務存在,掛起當前事務,建立一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式運行,若是有事務存在,掛起當前事務
PROPAGATION_NEVER 以非事務方式運行,若是有事務存在,拋出異常
PROPAGATION_NESTED 若是當前事務存在,則嵌套事務執行設計
1: PROPAGATION_REQUIRED
加入當前正要執行的事務不在另一個事務裏,那麼就起一個新的事務
好比說,ServiceB.methodB的事務級別定義爲PROPAGATION_REQUIRED, 那麼因爲執行ServiceA.methodA的時候,
ServiceA.methodA已經起了事務,這時調用ServiceB.methodB,ServiceB.methodB看到本身已經運行在ServiceA.methodA
的事務內部,就再也不起新的事務。而假如ServiceA.methodA運行的時候發現本身沒有在事務中,他就會爲本身分配一個事務。
這樣,在ServiceA.methodA或者在ServiceB.methodB內的任何地方出現異常,事務都會被回滾。即便ServiceB.methodB的事務已經被
提交,可是ServiceA.methodA在接下來fail要回滾,ServiceB.methodB也要回滾事務
2: PROPAGATION_SUPPORTS
若是當前在事務中,即以事務的形式運行,若是當前再也不一個事務中,那麼就以非事務的形式運行ci
3: PROPAGATION_MANDATORY
必須在一個事務中運行。也就是說,他只能被一個父事務調用。不然,他就要拋出異常it
4: PROPAGATION_REQUIRES_NEW
這個就比較繞口了。 好比咱們設計ServiceA.methodA的事務級別爲PROPAGATION_REQUIRED,ServiceB.methodB的事務級別爲PROPAGATION_REQUIRES_NEW,
那麼當執行到ServiceB.methodB的時候,ServiceA.methodA所在的事務就會掛起,ServiceB.methodB會起一個新的事務,等待ServiceB.methodB的事務完成之後,
他才繼續執行。他與PROPAGATION_REQUIRED 的事務區別在於事務的回滾程度了。由於ServiceB.methodB是新起一個事務,那麼就是存在
兩個不一樣的事務。若是ServiceB.methodB已經提交,那麼ServiceA.methodA失敗回滾,ServiceB.methodB是不會回滾的。若是ServiceB.methodB失敗回滾,
若是他拋出的異常被ServiceA.methodA捕獲,ServiceA.methodA事務仍然可能提交。io
5: PROPAGATION_NOT_SUPPORTED
當前不支持事務。好比ServiceA.methodA的事務級別是PROPAGATION_REQUIRED ,而ServiceB.methodB的事務級別是PROPAGATION_NOT_SUPPORTED ,
那麼當執行到ServiceB.methodB時,ServiceA.methodA的事務掛起,而他以非事務的狀態運行完,再繼續ServiceA.methodA的事務。
6: PROPAGATION_NEVER
不能在事務中運行。假設ServiceA.methodA的事務級別是PROPAGATION_REQUIRED, 而ServiceB.methodB的事務級別是PROPAGATION_NEVER ,
那麼ServiceB.methodB就要拋出異常了。
7: PROPAGATION_NESTED
理解Nested的關鍵是savepoint。他與PROPAGATION_REQUIRES_NEW的區別是,PROPAGATION_REQUIRES_NEW另起一個事務,將會與他的父事務相互獨立,
而Nested的事務和他的父事務是相依的,他的提交是要等和他的父事務一塊提交的。也就是說,若是父事務最後回滾,他也要回滾的。
而Nested事務的好處是他有一個savepoint。
Spring事務的隔離級別
1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別.
另外四個與JDBC的隔離級別相對應
2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級別,它充許令外一個事務能夠看到這個事務未提交的數據。
這種隔離級別會產生髒讀,不可重複讀和幻像讀。
3. ISOLATION_READ_COMMITTED: 保證一個事務修改的數據提交後才能被另一個事務讀取。另一個事務不能讀取該事務未提交的數據
4. ISOLATION_REPEATABLE_READ: 這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能出現幻像讀。
它除了保證一個事務不能讀取另外一個事務未提交的數據外,還保證了避免下面的狀況產生(不可重複讀)。
5. ISOLATION_SERIALIZABLE 這是花費最高代價可是最可靠的事務隔離級別。事務被處理爲順序執行。
除了防止髒讀,不可重複讀外,還避免了幻像讀。
什麼是髒數據,髒讀,不可重複讀,幻覺讀? 髒讀: 指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時, 另一個事務也訪問這個數據,而後使用了這個數據。由於這個數據是尚未提交的數據, 那麼另一 個事務讀到的這個數據是髒數據,依據髒數據所作的操做多是不正確的。 不可重複讀: 指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。 那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,那麼第一個事務兩次讀到的數據 多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。 幻覺讀: 指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及 到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼, 之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。