事務的四種隔離級別和七種傳播機制
事務四大特性:
* 原子性(Atomicity) :強調的事務的不可分割.
* 一致性(Consistency) :強調的事務的執行前後,資料庫的的完整性保持一致.
* 隔離性(Isolation) :強調的事務的併發的訪問,一個事務的執行,不應該受到另一個事務的打擾.
* 永續性(Durability) :強調的事務結束之後,資料就永久的儲存的資料庫中.
* 安全性:read uncommitted < read committed < repeatable read < serializable* 效率:read uncommitted > read committed > repeatable read > serializable
資料庫事務的隔離級別有4種,由低到高分別為Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事務的併發操作中可能會出現髒讀,不可重複讀,幻讀。
1. ISOLATION_READ_UNCOMMITTED:這是事務最低的隔離級別,A事務可以看到B事務未提交的資料
這種隔離級別會產生髒讀,不可重複讀和幻像讀。
事例:代靜給郭華髮工資,一個月一塊,但是代靜按錯了,發成了兩塊,該錢已經打到了郭華的賬戶,但是事務還沒有提交,郭華髮現了自己的賬戶多了一塊,但是代靜及時發現了,修改了又提交了事務(郭華可以看到代靜未提交的事務,這就出現了髒讀問題)
2. ISOLATION_READ_COMMITTED:A事務可以讀取B事務修改後提交的資料,但是不能讀取B事務未提交的資料
事例:郭華去吃飯,買單時(事務已開啟),代靜把郭華的錢轉走了,這時郭華髮現卡里沒錢了(飯店老闆的事務要等到代靜的轉錢事務操作提交後,他才能讀取資料)
一個事務範圍內兩個相同的查詢卻返回了不同資料,這就是不可重複讀
3. ISOLATION_REPEATABLE_READ:這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。
它除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了避免下面的情況產生(不可重複讀)。
事例:郭華去吃飯,買單時(事務已開啟),代靜不能進行轉錢操作,避免了不可重複讀的問題
(但是可能出現幻讀問題,幻讀問題對應的是插入INSERT操作,而不是UPDATE操作)
4. ISOLATION_SERIALIZABLE:這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止髒讀,不可重複讀外,還避免了幻像讀。
大多數資料庫預設的事務隔離級別是Read committed,比如Sql Server , Oracle。MySQL的預設隔離級別是Repeatable read。
髒讀:A事務處理過程中讀取了B事務未提交的資料,這就是髒讀
不可重複讀:不可重複讀取是指同一個事務在整個事務過程中對同一筆資料進行讀取,每次讀取結果都不同
幻讀:是指同樣一筆查詢在整個事務過程中多次執行後,查詢所得的結果集是不一樣的。幻讀針對的是多筆記錄
七種轉播機制
1: PROPAGATION_REQUIRED
加入當前正要執行的事務不在另外一個事務裡,那麼就起一個新的事務
例如:
ServiceB.methodB的事務級別定義為PROPAGATION_REQUIRED
ServiceA.methodA已經起了事務,這時呼叫ServiceB.methodB,ServiceB.methodB就加入ServiceA.methodA的事務內部,就不再起新的事務。ServiceA.methodA沒有在事務中,這時呼叫ServiceB.methodB,
ServiceB.methodB就會為自己分配一個事務。
在ServiceA.methodA或者在ServiceB.methodB內的任何地方出現異常,事務都會被回滾。即使ServiceB.methodB的事務已經被提交,但是ServiceA.methodA在接下來fail要回滾,ServiceB.methodB也要回滾
2: PROPAGATION_SUPPORTS
如果當前在事務中,即以事務的形式執行,如果當前不再一個事務中,那麼就以非事務的形式執行
3: PROPAGATION_MANDATORY
必須在一個事務中執行。也就是說,他只能被一個父事務呼叫。否則,他就要丟擲異常
4: PROPAGATION_REQUIRES_NEW
例如:
ServiceA.methodA的事務級別為PROPAGATION_REQUIRED,ServiceB.methodB的事務級別為PROPAGATION_REQUIRES_NEW,
當呼叫ServiceB.methodB的時候,ServiceA.methodA所在的事務就會掛起,ServiceB.methodB會起一個新的事務,等待ServiceB.methodB的事務完成以後,他才繼續執行。
PROPAGATION_REQUIRES_NEW與PROPAGATION_REQUIRED 的事務區別在於事務的回滾程度:
因為ServiceB.methodB和ServiceA.methodA兩個不同的事務。如果ServiceB.methodB已經提交,那麼ServiceA.methodA失敗回滾,ServiceB.methodB是不會回滾的。如果ServiceB.methodB失敗回滾,
如果他丟擲的異常被ServiceA.methodA捕獲,ServiceA.methodA事務仍然可能提交。
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。