資料庫併發問題及事物隔離級別問題:髒讀,不可重複讀,幻讀,第一類丟失更新,第二類丟失更新
阿新 • • 發佈:2018-12-17
資料庫併發問題:髒讀,不可重複讀,幻讀,第一類丟失更新,第二類丟失更新
一個數據庫,多個客戶端併發訪問資料庫。在資料庫中的相同資料可能被多個事物同時訪問,如果沒有采取必要的隔離措施,就會導致併發問題,破壞資料的完整性。這些問題可以歸結為5類:3類資料庫讀問題,2類資料庫更新問題。
1.髒讀(dirty read)
A事物讀取B事物尚未提交更改的資料,並在這個資料的基礎上操作。如果B事物恰巧回滾,那麼A事物讀取到的事物是根本不被承認的。如下列:
時間 | 事物A | 事物B |
T1 | 開始事物 | |
T2 | 開始事物 | |
T3 | 查詢餘額1000元 | |
T4 | 取出500元,餘額改為500元 | |
T5 | 查詢餘額500元(髒讀) | |
T6 | 撤銷事物餘額1000元 | |
T7 | 匯入100元,餘額改為600元 | |
T8 | 提交事物 |
在這個場景中B希望取出500元,而後又撤銷了動作,而A往相同賬戶轉入100元,就因為A讀取到了B未提交更改資料,造成賬戶白白丟失500元。(注:在oracal資料庫中,不會發生髒讀的情況)
2.不可重複讀(unrepeatable read)
不可重複讀是指:A事物讀取到B事物已提交的更改資料。假設A在取款事物過程中,B往賬戶轉入100元,A兩次讀取到的餘額不一致。
時間 | 事物A | 事物B |
T1 | 開始事物 | |
T2 | 開始事物 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 查詢賬戶餘額位1000元 | |
T5 | 取出100元,修改餘額為900元 | |
T6 | 提交事物 | |
T7 | 查詢賬戶餘額900元(和T4查詢不一致) |
同一事物中兩次查詢賬戶餘額不一致
3.幻讀(phantom read)
A事物讀取B事物提交的新增資料,這時A事物將出現幻讀
時間 | 事物A | 事物B |
T1 | 開始事物 | |
T2 | 開始事物 | |
T3 | 統計賬戶總存款為10000元 | |
T4 | 新增一個存款賬戶,並轉入100元 | |
T5 | 提交事物 | |
T6 | 再次統計存款為10100元(幻讀) |
如果新增資料剛好滿足查詢條件,這個資料就會進入事物的視野,因而產生兩次統計結果不一致的情況
注:幻讀和不可重複讀的區別在於前者讀取到的是已提交的新增資料,後者讀取到的是已提交的更新資料(或者刪除的資料)。為了避免這兩種情況,採取的策略是不同的,防止讀到更改操作,只需要對操作資料新增行級鎖,阻止操作中的資料發生變化;而防止讀到新增資料,則往往新增表級鎖--將整張表鎖定,防止新增資料(Oracal通過多版本資料的方式實現)
4.第一類丟失資料更新
A事物撤銷時,覆蓋掉 B事物已提交的更新資料。
時間 | 事物A | 事物B |
T1 | 開始事物 | |
T2 | 開始事物 | |
T3 | 查詢賬戶為1000元 | |
T4 | 查詢賬戶為1000元 | |
T5 | 轉入100元,修改餘額為1100元 | |
T6 | 提交事物 | |
T7 | 取出100元,修改餘額為900元 | |
T8 | 撤銷事物(或提交事物) | |
T9 | 餘額回覆為1000元(丟失更新) |
A事物在撤銷時,將B事物轉入的100元抹去了
5.第二類丟失更新
A事物覆蓋B事物已提交的資料,造成B事物所有的操作丟失
時間 | 事物A | 事物B |
T1 | 開始事物 | |
T2 | 開始事物 | |
T3 | 查詢賬戶為1000元 | |
T4 | 查詢賬戶為1000元 | |
T5 | 取出100元,修改餘額為900元 | |
T6 | 提交事物 | |
T7 | 轉入100元 | |
T8 | 提交事物 | |
T9 | 修改餘額為1100元(丟失更新) |
6.事物隔離級別及影響