数据库事务隔离标准分析
1 概述與背景
這是數(shù)據(jù)庫事務(wù)原理和工程實踐系列文章的第一篇,本文主要在Jim Gray的論文<A Critique of ANSI SQL Isolation Levels>基礎(chǔ)上分析關(guān)系數(shù)據(jù)庫的事務(wù)隔離級別標(biāo)準(zhǔn)和不同隔離級別情況下的行為。第2節(jié)主要討論ANSI標(biāo)準(zhǔn)的下的隔離級別,第3節(jié)主要討論基于悲觀鎖實現(xiàn)的事務(wù)隔離級別,第4節(jié)主要討論基于多版本技術(shù)的事務(wù)隔離,最后總結(jié)排序本文討論到的各個隔離級別。
ACID是關(guān)系數(shù)據(jù)庫的一組重要特性,其中Isolation(隔離性)描述了數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止多個事務(wù)并發(fā)時由于交錯執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。在最極端的情況下,數(shù)據(jù)庫完全串行化執(zhí)行每一個事務(wù),所有事務(wù)之間遵守全序關(guān)系,在這種情況下,不存在并發(fā)事務(wù)間的隔離問題,但是在實際工程實踐中,處于對數(shù)據(jù)庫性能吞吐量的考慮,允許多個事務(wù)之間按照一定的規(guī)則,打破串行話的全序關(guān)系,ANSI SQL Isolation Levels即規(guī)定了這種“規(guī)則”,通過將隔離性劃分為4個級別,來換取多層級的事務(wù)間并發(fā)能力(即數(shù)據(jù)庫的吞吐能力)。
注,本文內(nèi)容融入了作者個人的理解,并沒有嚴(yán)格遵守<A Critique of ANSI SQL Isolation Levels>原文的內(nèi)容;其中cursor stability隔離級別將在后續(xù)文章中討論,快照隔離級別與ANSI標(biāo)準(zhǔn)異象的比較也有所不同。
2 ANSI事務(wù)隔離級別
ANSI SQL-92標(biāo)準(zhǔn)(http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)將數(shù)據(jù)庫并發(fā)事務(wù)間的隔離性行為劃分為3種"異象(phenomena)",從低到高的自然語言定義依次為:
P1?臟讀 ("Dirty read"): SQL-transaction T1 modifies a row. SQL- transaction T2 then reads that row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 will have read a row that was never committed and that may thus be considered to have never existed.?
P2 不可重復(fù)讀 ("Non-repeatable read"): SQL-transaction T1 reads a row. SQL- transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.?
P3 幻讀 ("Phantom"): SQL-transaction T1 reads the set of rows N that satisfy some <search condition>. SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the <search condition> used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same <search condition>, it obtains a different collection of rows.
通過依次禁止這三種異象,ANSI確定了4種標(biāo)準(zhǔn)隔離級別,如下表所示:
| 級別 | P1(臟讀) | P2(不可重復(fù)讀) | P3(幻讀) | 
| Read Uncommitted | 允許 | 允許 | 允許 | 
| Read Committed | 禁止 | 允許 | 允許 | 
| Repeatable Read | 禁止 | 禁止 | 允許 | 
| (Anomaly) Serializable | 禁止 | 禁止 | 禁止 | 
| Note: The exclusion of these penomena or SQL-transactions executing at isolation level SERIALIZABLE is a consequence of the requirement that such transactions be serializable. | |||
如標(biāo)準(zhǔn)文檔所述,禁止了P1/P2/P3異象的事務(wù)即滿足Serializable級別,但矛盾的是,標(biāo)準(zhǔn)文檔中對Serializable又做了如下說明:
| The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions | 
它要求多個并發(fā)事務(wù)執(zhí)行的效果與某種串行化執(zhí)行的效果一致,但是僅僅禁止P1/P2/P3異象,并不一定能夠保證“serial execution”的效果,因此論文中將ANSI Serializable稱為Anomaly Serializable。
P1/P2/P3的形式化描述
根據(jù)標(biāo)準(zhǔn)文檔的定義,可以將這三種異象使用形式化語言描述如下,稱為A1/A2/A3(其中w1[x]表示事務(wù)1寫入記錄x,r1表示事務(wù)1讀取記錄x,c1表示事務(wù)1提交,a1表示事務(wù)1回滾,r1[P]表示事務(wù)1按照謂詞P的條件讀取若干條記錄,w1[y in P]表示事務(wù)1寫入記錄y滿足謂詞P的條件):
A1 臟讀:w1[x] ... r2[x] ... (a1 and c2 in any order)
A2 不可重復(fù)讀:r1[x] ... w2[x] ... c2 ... r1[x] ... c1
A3 幻讀:r1[P] ... w2[y in P] ... c2 ... r1[P] ... c1
上述A1/A2/A3形式化描述,根據(jù)標(biāo)準(zhǔn)定義的P1/P2/P3異象的自然語言描述轉(zhuǎn)化而來,但是ANSI標(biāo)準(zhǔn)定義的異象只針對了單個記錄或謂詞描述,對于多條記錄需滿足業(yè)務(wù)一致性的場景并未能覆蓋(比如兩個賬戶間轉(zhuǎn)賬要求余額總和不變),舉例如下:
H1:r1[x=50]w1[x=10]?r2[x=10]r2[y=50]?c2 r1[y=50]w1[y=90] c1
事務(wù)1執(zhí)行賬戶x向賬戶y轉(zhuǎn)賬40,事務(wù)2讀取到了進(jìn)行到了一半的事務(wù)1(Read Uncommitted),破壞了余額總和的一致性
因為事務(wù)1并未回滾,H1的行為并不符合A1的形式化定義
H2:r1[x=50]?r2[x=50]w2[x=10]r2[y=50]w2[y=90] c2?r1[y=90]?c1
事務(wù)2執(zhí)行賬戶x向賬戶y轉(zhuǎn)賬40,事務(wù)1在事務(wù)2提交前后讀取到了破壞余額總和一致性的數(shù)據(jù)(Unrepeatable Read)
因為事務(wù)1并未重復(fù)讀取記錄x,H2的行為并不符合A2的形式化定義
H3:r1[P]?w2[insert y to P] r2[z] w2[z] c2?r1[z]?c1
事務(wù)2增加新雇員并更新雇員總數(shù)z,事務(wù)1在事務(wù)2提交前后讀取到了破壞雇員列表與雇員總數(shù)的一致性的數(shù)據(jù)(Phantom)
因為事務(wù)1并未重復(fù)讀取謂詞P指定的數(shù)據(jù)集合,H3的行為并不符合A3的形式化定義
因為要增強對上述H1/H2/H3異象的約束,論文將A1/A2/A3的形式化描述稱為“狹義的描述(strict interpretations)”,然后增加了“廣義的描述(broad interpretation)”,去除了strict interpretations中對事務(wù)提交、回滾和數(shù)據(jù)讀取范圍的約束,只保留事務(wù)之間讀寫的時序關(guān)系,即事務(wù)之間只要包含如下時序的操作,即可能產(chǎn)生包含H1/H2/H3在內(nèi)的異象,如下:
P1 臟讀:w1[x] ... r2[x] ... ((c1 or a1) and (c2 or a2) in any order)
P2 不可重復(fù)讀:r1[x] ... w2[x] ...?((c1 or a1) and (c2 or a2) in any order)
P3 幻讀:r1[P] ... w2[y in P]?...?((c1 or a1) and (c2 or a2) in any order)
在上述形式化描述下,禁止P1即可禁止H1,禁止P1/P2即可禁止H2,禁止P1/P2/P3即可禁止H3。至此,ANSI標(biāo)準(zhǔn)隔離級別定義的三種異象,可以被擴展為適用范圍更廣的的P1/P2/P3的形式化定義,這種隔離級別定義被論文稱之為“phenomena-based”,即基于“異象”的隔離級別定義。
3 基于鎖的事務(wù)隔離
在上一節(jié)的討論中,P1/P2/P3這三種形式化定義指出了三個不同級別的異象,但是并沒有與實際的工程實踐相關(guān)聯(lián),在本小節(jié)中,我們將介紹基于鎖(lock base)的事務(wù)隔離實現(xiàn),并且將不同的加鎖行為與上述三種異象關(guān)聯(lián)起來討論。
在討論加鎖行為之前,需要定義如下幾種讀寫和鎖的操作:
Predicate lock 謂詞鎖(gap鎖):Locks on all data items satisfying the search condition
Well-formed Writes 合法write:Requests a Write(Exclusive) lock on each data item or predicate before writing
Well-formed Reads 合法read:Requests a Read(share) lock on each data item or predicate before reading
Long duration locks 長周期鎖:Locks are held until after the transaction commits or aborts
Shord duration locks 短周期鎖:Locks are released immediately after the action completes
通過組合上述讀寫鎖操作,我們能夠構(gòu)建不同級別的事務(wù)隔離標(biāo)準(zhǔn)。因為“No Well-formed Writes”或“Short duration write locks”的保護等級可能造成dirty write,它的約束已經(jīng)低到難以找到實際應(yīng)用場景,我們將其忽略,因此所有寫入操作都使用“Well-formed Writes,?Long duration Write locks”,通過對讀取操作應(yīng)用不同的保護等級,得到4種隔離級別,使用locking前綴與ANSI隔離級別區(qū)分,如下表所示:
| Read Lock | Write Lock | |
| Locking Read Uncommited  | none required  | Well-formed Writes, Long duration Write locks  | 
| Locking Read Commited  | Well-formed Reads, Short duration read lock  | Well-formed Writes, Long duration Write locks  | 
| Locking Repeatable Read  | Well-formed Reads, Long duration data-item Read locks, Short duration Read Predicate locks  | Well-formed Writes Long duration Write locks  | 
| Locking Serializable  | Well-formed Reads, Long duration Read locks  | Well-formed Writes Long duration Write locks  | 
將locking標(biāo)記的四種隔離級別與ANSI隔離級別對比:
Well-formed Reads,?Short duration read lock?禁止了 P1發(fā)生,r2[x]將被讀鎖阻塞,直到事務(wù)1提交或回滾
Well-formed Reads,?Long duration data-item Read locks,?Short duration Read Predicate locks?禁止了P2發(fā)生,w2[x]將被寫鎖阻塞,直到事務(wù)1提交或回滾
其中Short duration Read Predicate locks的作用論文中并沒有說明,實際上它保護了r[P]的一致性,保證r[P]讀取到的多行數(shù)據(jù)是一個“well-formed history”
Well-formed Reads,?Long duration Read locks?禁止了P3發(fā)生,w2[y in P]將被謂詞寫鎖阻塞,直到事務(wù)1提交或回滾
如上所述,Lock Base的隔離級別能夠完全覆蓋ANSI基于異象的隔離級別約束,論文中也稱“phenomena-based”是“disguised versions of locking”。
4 基于快照的事務(wù)隔離
對于基于鎖實現(xiàn)事務(wù)隔離的數(shù)據(jù)庫,讀寫、寫寫事務(wù)之間也可能因為鎖沖突而被阻塞,數(shù)據(jù)庫的整體吞吐能力受到比較大的限制,特別是在目前多核的CPU條件下,難以充分發(fā)揮計算能力。因此現(xiàn)代關(guān)系型數(shù)據(jù)庫和NewSQL,比如MySQL/Oracle/PostgreSQL/OceanBase/TiDB等,都使用多版本并發(fā)控制(mvcc)技術(shù),來實現(xiàn)事務(wù)隔離,它的核心設(shè)計思想是,為數(shù)據(jù)的每次修改保存一個用時間戳標(biāo)記的版本,數(shù)據(jù)讀取不需要加鎖,而是在讀取事務(wù)開始的時候獲取當(dāng)前時間戳(snapshot),對于每條數(shù)據(jù),將版本號小于snapshot的最大已提交版本的內(nèi)容作為讀取結(jié)果返回。
Snapshot Isolation保證只讀事務(wù)與讀寫事務(wù)相互不阻塞,只讀事務(wù)通過讀取合法的歷史快照,保證了讀取到的數(shù)據(jù)的一致性,我們在快照隔離下與A1/A2/A3逐個對比分析:
P1描述的w1[x] ... r2[x] ...操作時序不可能出現(xiàn),因為在快照隔離下,實際的操作時序為w1[x] ... r2[last version of x] ...,因此可知快照隔離禁止P1
P2描述的r1[x] ... w2[x] ... 它實際的操作時序為r1[x] ... w2[new version of x] ...,可以知道快照隔離也禁止了P2。至此,我們可以確定快照隔離的效果至少大于Read Committed
P3描述的r1[P] ... w2[y in P] ... 它實際的操作時序為r1[P] ... w2[new version of y in P] ...,可以知道快照隔離也禁止了P3,達(dá)到了第2小節(jié)中ANSI的Anomaly?Serializable級別
但是,從上一小節(jié)基于鎖的隔離級別定義來分析,快照隔離的安全級別可能并沒有那么高,我們來看如下兩種異象的形式化描述:
A5A Read Skew: r1[x]...w2[x]...w2[y]...c2...r1[y]...(c1 or a1)
A5B Writer Skew: r1[x]...r2[y]...w1[y]...w2[x]...(c1 and c2 occur)
擴展的Write Skew(并非來自原文):r1[P]...r2[P]...w1[x]...w2[y]...(c1 and c2 occur)
快照隔離性高于Read Committed:第一,考慮到快照隔離讀已提交的數(shù)據(jù)版本的特性,禁止了P1,因此保證至少不低于Read Committed。第二,A5A的Read Skew異象符合P2的定義,并且從一致性的角度分析,事務(wù)1對x和y的讀取的兩個值不在線性的歷史中,可能會違背某種外部約束(比如保證x+y的和為一個常量),因此Read Committed隔離級別下允許A5A Read Skew異象??偤鸵陨蟽牲c,我們可以得出結(jié)論,快照隔離性高于Read Committed。
快照隔離性與Repeatable Read不相容:考慮到快照隔離能夠保證讀取到的數(shù)據(jù)在一個一致的歷史快照上,禁止了P1/P2/P3,因此保證不低于ANSI的Anomaly?Serializable級別;但是,另一方面,經(jīng)典的快照隔離對于多寫沖突是基于First- committer-wins的處理方式,依賴沖突的事務(wù)間至少修改同一條記錄(現(xiàn)代快照隔離有更優(yōu)的SSI,我們將在后續(xù)的文章中介紹)無法避免上述A5B Write Skew的兩種異象,而基于鎖事項的Repeatable Read級別卻可以禁止A5B??煺崭綦x與Repeatable Read雙方禁止的異象,有可能在對方出現(xiàn),因此他們的隔離性無法相比較。
5 總結(jié)
從前面幾個小節(jié)的隔離性分析來看,我們可以得到如下幾種隔離級別的關(guān)系:
| Read Uncommitted?<?Read Committed?<?(Repeatable Read?><?Snapshot)?<?Serializable | 
本文首先介紹了ANSI基于“異象”的隔離級別標(biāo)準(zhǔn),并分析了其狹義和廣義的描述;然后介紹了基于鎖的隔離級別標(biāo)準(zhǔn),與ANSI隔離級別進(jìn)行了比較;最后分析快照隔離級別,在ANSI隔離級別標(biāo)準(zhǔn)基礎(chǔ)上,提出了兩種新的“異象”,得出快照隔離在幾種標(biāo)準(zhǔn)隔離級別特性中的位置。
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/31556421/viewspace-2218934/,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任。
轉(zhuǎn)載于:http://blog.itpub.net/31556421/viewspace-2218934/
總結(jié)
以上是生活随笔為你收集整理的数据库事务隔离标准分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Ubuntu下使用ROS moveit
 - 下一篇: 相位解包裹(五)枝切法(Goldstei