天天看點

資料并發的問題

一個資料庫可能擁有多個通路用戶端,這些用戶端都可以并發方式通路資料庫。資料庫中的相同資料可能同時被多個事務通路,如果沒有采取必要的隔離措施,就會導緻各種并發問題,破壞資料的完整性。這些問題可以歸結為5類,包括3類資料讀問題(髒讀、不可重複讀和幻象讀)以及2類資料更新問題(第一類丢失更新和第二類丢失更新)。下面,我們分别通過執行個體講解引發問題的場景。

髒讀(Dirty read)

A事務讀取B事務尚未送出的更改資料,并在這個資料的基礎上操作。如果恰巧B事務復原,那麼A事務讀到的資料根本是不被承認的。來看取款事務和轉賬事務并發時引發的髒讀場景:

資料并發的問題

在這個場景中,B希望取款500元而後又撤銷了動作,而A往相同的賬戶中轉賬100元,就因為A事務讀取了B事務尚未送出的資料,因而造成賬戶白白丢失了500元。在Oracle資料庫中,不會發生髒讀的情況。

不可重複讀(Unrepeatable read)

不可重複讀是指A事務讀取了B事務已經送出的更改資料。假設A在取款事務的過程中,B往該賬戶轉賬100元,A兩次讀取賬戶的餘額發生不一緻:

資料并發的問題
資料并發的問題

在同一事務中,T4時間點和T7時間點讀取賬戶存款餘額不一樣。

幻象讀(Phantom read)

A事務讀取B事務送出的新增資料,這時A事務将出現幻象讀的問題。幻象讀一般發生在計算統計資料的事務中,舉一個例子,假設銀行系統在同一個事務中,兩次統計存款賬戶的總金額,在兩次統計過程中,剛好新增了一個存款賬戶,并存入100元,這時,兩次統計的總金額将不一緻:

資料并發的問題

如果新增資料剛好滿足事務的查詢條件,這個新資料就進入了事務的視野,因而産生了兩個統計不一緻的情況。

幻象讀和不可重複讀是兩個容易混淆的概念,前者是指讀到了其他已經送出事務的新增資料,而後者是指讀到了已經送出事務的更改資料(更改或删除),為了避免這兩種情況,采取的對策是不同的,防止讀取到更改資料,隻需要對操作的資料添加行級鎖,阻止操作中的資料發生變化,而防止讀取到新增資料,則往往需要添加表級鎖——将整個表鎖定,防止新增資料(Oracle使用多版本資料的方式實作)。

第一類丢失更新

A事務撤銷時,把已經送出的B事務的更新資料覆寫了。這種錯誤可能造成很嚴重的問題,通過下面的賬戶取款轉賬就可以看出來:

資料并發的問題

A事務在撤銷時,“不小心”将B事務已經轉入賬戶的金額給抹去了。

第二類丢失更新

A事務覆寫B事務已經送出的資料,造成B事務所做操作丢失:

資料并發的問題

面的例子裡由于支票轉賬事務覆寫了取款事務對存款餘額所做的更新,導緻銀行最後損失了100元,相反如果轉賬事務先送出,那麼使用者賬戶将損失100元。