資料庫的事務和併發問題

2021-08-28 13:57:17 字數 3590 閱讀 4392

事務(transaction)是併發控制的基本單位。所謂的事務,它是乙個操作序列,這些操作要麼全部執行,要麼全部都不執行。比如,銀行轉賬,從乙個賬號扣錢,然後另乙個賬號餘額增加,這兩個操作要麼都執行,要麼都不執行。這兩個操作組合在一起就是事務。

資料庫事務有嚴格的定義,它必須同時滿足4個特性:

原子性,atomic

一致性,consistency

隔離性, isolation

永續性,durabiliy

簡稱acdi。下面是對每乙個特性的說明:

在這些事務的特徵中,資料」一致性「是最終目標,其他特性都是為達到這個目標而採取的措施。

乙個資料庫可能會有多個客戶端同時訪問,資料庫中相同的資料就有可能同時被多個事務訪問,如果沒有採取必要的隔離措施,就會導致各種問題,破壞資料的完整性,這些問題可以分為5中,兩類:

資料讀取的問題:

資料更新問題

1. 髒讀(direct read)

a事務讀取b事務尚未提交更改的資料,並在這個資料的基礎上進行操作。如果恰巧b事務回滾,那麼a事務讀取到的資料是不被承認的。通過乙個取款事務和轉賬事務來說明這個問題。

時間轉賬事務a

取款事務b

t1開始事務

t2開始事務

查詢賬戶餘額1000元

t3取出500元,把餘額改為500元

t4查詢餘額500元(髒讀)

t5撤銷事務,餘額恢復為1000元

t6匯入100元,把餘額改為600元

t8提交事務

在這個場景中轉賬事務a讀取到取款事務b中的未提交的資料,導致髒讀。

2. 不可重複讀(unrepeatable read)

不可重複讀是指a事務讀取b事務已經提交更改的資料。假設a在取款事務的過程中,b往該賬戶轉賬100元,a兩次讀取賬戶的餘額不一致。

時間取款事務a

轉賬事務b

t1開始事務

t2開始事務

t3查詢賬戶餘額為1000元

t4查詢賬戶餘額1000元

t5取出100元,把餘額改為900元

t6查詢事務

t7查詢賬戶餘額為900元

在同一事務中,t4和t7時間點讀取的賬戶餘額不一致。

3. 幻想讀(phantom read)

a事務讀取b事務提交的新增資料,這時a事務將出現幻想讀現象。幻想讀一般發生在計算統計資料的事務中。

舉個例子,比如在銀行系統的同乙個事務中有兩次統計存款使用者的總金額,在兩次統計中剛好新增了乙個存款,這時,兩次統計的結構將會不一致。

時間統計金額事務a

轉賬事務b

t1開始事務

t2開始事務

t3統計總存款為1000元

t4新增乙個存款賬戶,存款100元

55提交事務

t6再次統計總存款數為10100元(幻想讀)

如果新增的資料剛好滿足事務的查詢條件,那麼這個新資料就會出現事務的視野中,因而產生了兩次結構不一致。

幻想讀和不可重複讀這兩個概念比較容易混淆

,幻想讀是指讀到了其他已經提交的事務的新增資料,而不可重複讀是指讀到了已經提交的更改資料(更改或者刪除)。

為了避免這兩種情況,採取的對策是不同的:防止讀到更新的資料,只需要對操作的資料新增行級鎖,阻止操作中的資料發生改變;而防止讀到新增的資料,則往往需要新增表級鎖——將整張表加鎖,防止新增資料。

4. 第一類丟失更新

第一類丟失更新是乙個事務撤銷時把另乙個事務的資料覆蓋了。下面通過乙個轉賬的例子來看一下這個問題。

時間取款事務a

轉賬事務b

t1開始事務

t2開始事務

t3查詢餘額為1000元

t4查詢餘額為1000元

t5匯入100元,把餘額修改為1100元

t6提交事務

t7取出100元,把餘額修改為900元

t8撤銷修改

t9把餘額恢復為1000元(丟失更新)

5. 第二類丟失更新

乙個事務覆蓋另乙個事務已經提交的資料。造成另乙個事務所做的操作丟失。

時間取款事務a

轉賬事務b

t1開始事務

t2開始事務

t3查詢賬戶餘額為1000元

t4查詢賬戶餘額為1000元

t5取出100元,把餘額修改為900元

t6提交事務

t7匯入100元

t8提交事務

t9把餘額修改為1100元(丟失更新)

總結:第一類為撤銷時覆蓋,第二類為提交時覆蓋。

資料庫的併發會引起很多問題,當然有些問題還可以容忍,但是有的問題卻是致命的。併發問題一般都會用鎖解決,在資料庫中也是用鎖解決的,但是不同的資料庫對於鎖的實現是不同的,但基本的原理是相同。

按鎖定的物件可以分為:

從併發的資料關係中又可以分為

在資料更新的時候,資料庫必須在進行更改的行上施加行獨佔鎖,也就是說insert,update,delete等語句都會隱式採用必要的行鎖定。

儘管資料庫為使用者提供了鎖的dml操作方式,但是直接使用還是很麻煩的,因此資料庫為使用者提供了自動鎖的機制。也就是隔離級別,只要使用者指定的回話的隔離級別,資料庫就會分析sql語句,然後進行合適的加鎖,當資料鎖的資料太多的時候,自動進行鎖公升級來提高系統的,效能,這一過程對使用者是透明的(不可見)的。

sql標準定義了4個事務級別,每乙個級別都規定了乙個事務中所做的修改,哪些在事務中是可見的,哪些是不可見的。較低的隔離通常可以執行更高的併發,系統開銷也更低。

下面的是四中資料庫事務的介紹:

read uncommited(未提交讀)

事務中的修改,即使沒有提交對其它事務都是可見的。事務可以讀取未提交的資料,這也被稱為髒讀。一般很少使用。

read commited(提交讀)

大多數的資料庫的預設隔離級別都是read commited。read_commited從乙個事務開始時,只能」看見「已經提交的修改。也就是說:乙個事務從開始到提交前,所做的任何修改對其他事務是不可見的。這個級別有時候也叫做不可重複讀,因為兩次執行查詢可能會得到不同的結果。

repeatable read(可重複讀)

repeatable read解決了髒讀的問題,該級別保證在同乙個事務中多次讀取同樣的記錄的結果是一致的。但是這個級別還是沒有解決另乙個問題:幻讀。

serializable(可序列化)

serializable是最高的隔離級別。它通過事務串執行,避免了前面所說的幻讀問題。簡單來說serializable會為每一行資料都加鎖,所以會導致大量的鎖超時和競爭。實際中很少使用這個隔離級別。

下表為事務隔離級別對併發問題的解決情況:

隔離級別

髒讀不可重複讀

幻想讀第一類丟失更新

第二類丟失更新

read uncommited

允許允許

允許不允許

允許read commited

不允許允許

允許不允許

允許repeatable read

不允許不允許

允許不允許

不允許serializable

不允許不允許

不允許不允許

不允許其中read uncommited併發性和吞吐量最好,serializable的最差,所以事務的隔離級別和資料庫的並發行是對立的。

資料庫事務併發問題

乙個資料庫可能擁有多個訪問客戶端,這些客戶端都可以併發方式訪問資料庫。資料庫中的相同資料可能同時被多個事務訪問,如果沒有採取必要的隔離措施,就會導致各種併發問題,破壞資料的完整性。這些問題可以歸結為 5類,包括 3類資料讀問題 髒讀 幻象讀和不可重複讀 以及 2類資料更新問題 第一類丟失更新和第二類...

資料庫事務併發問題

多個事務同時訪問資料庫時候,會發生下列5類問題,包括3類資料讀問題 髒讀,不可重複讀,幻讀 2類資料更新問題 第一類丟失更新,第二類丟失更新 1,髒讀 dirty read a事務讀取b事務尚未提交的更改資料,並在這個資料基礎上操作。如果b事務回滾,那麼a事務讀到的資料根本不是合法的,稱為髒讀。在o...

資料庫中事務併發問題

對於同時執行的多個事務,當這些事務訪問資料庫中相同的資料時,如果沒有採取必要的隔離機制。就會導致各種併發問題 資料庫事務的隔離性 資料庫系統必須具有隔離併發執行各個事務的能力,使它們不會互相影響,避免各種併發問題。乙個事務與其他事務隔離的程度稱為隔離級別。資料庫規定了多種事務隔離級別,不同隔離級別對...