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