標籤:style blog http color io os ar 資料 2014
一、含義
資料庫管理系統中,事務需要滿足ACID四個特性。
Atomicity,即原子性,表示一個事務內的所有操作要麼全做,要麼全不做。
Consistency,即一致性,表示一個事務只能使資料庫從一個一致的狀態跳轉到另一個的一致性的狀態,不能破壞諸如主鍵唯一或者某列的所有值之和為固定值(轉賬不能影響存款總額)之類的約束。
Isolation,即隔離性,表示兩個事務之間互相不影響,就如同兩個事務串列一般。
durability,即持久性,表示如果一個事務如何成功了,它的影響是持久的,不會丟失。持久性通過將資料持久化到磁碟上來保證,當然如果磁碟壞掉了資料還是會丟失的,多副本可以極大地避免資料丟失,使可靠性達到更多個9的層級。
資料庫經常需要並發同時處理多個事務,讓所有相關的事務串列,可以完整地保證ACID特性,但這樣TPS會比較低,資料庫系統可以說是基本不可用了。因此,為了提高並發度,我們需要降低隔離性要求。根據業務具體需要,我們需要在並發度和隔離等級之間做trade off,通用的DBMS一般都會提供多個隔離等級供使用者選用。
二、異常現象2.1 髒寫(dirty write)
有兩個事務T1和T2,T1更改了某列x,在T1提交之前,T2隨之也更改了x,這就是髒寫,因為T1還沒提交,T2更改的是T1的中間狀態。假如現在T2提交了,T1要復原,如果復原到T1開始前的狀態,已經提交的T2的操作就全部丟失了,假如不復原到T1開始前的狀態,已經roll back的T1的影響就還存在資料庫中。允許這種現象的資料庫基本是停用,因為其已經不能完成事務roll back了。
2.2 髒讀(dirty read)
有兩個事務T1和T2,T1更改將列x從0更改為5,在T1提交之前,T2讀x進行讀取操作,讀到T1的中間狀態x = 5,假設最終T1 rollback了,而T2又依據T1的中間狀態x = 5做一些操作,最終就會出現一些不合理的結果。
2.3 不可重複讀取(fuzzy read)
有兩個事務T1和T2,T1先讀了x,然後T2更改了x,然後提交,這時如果T1再次讀x,則會出現在一個事務內兩次讀的x的結果是不一樣的。
2.4 幻讀(phantom read)
有兩個事務T1和T2,T1根據一個condition從table test select滿足條件的行,隨後T2往table test裡insert滿足Condition的行或者update不滿足條件使其滿足條件然後提交,這時如果T1再次通過condition select的話,則會出現一個事務內兩次按條件select的結果是不一樣的。
2.5 丟失更新(loss of update)
有兩個事務T1和T2,T1先讀x,讀到x = 0,然後T2讀x,讀到x = 0,接著T1講x加3,然後提交,接著T1將x加4,然後提交。這樣,x的值最終為4,T1的更新丟失了,如果T1和T2串列的話,最終結果會為7。
2.6 讀偏斜(read skew)
假如需要滿足約束x + y = 10,初始時x = 5, y = 5,事務T1先讀到x = 5,然後事務T2將x改為4,y改為6,然後提交,事務T1接著讀到y = 6,此時事務T1看到x + y = 11不滿足約束x + y = 10。
2.7 寫偏斜(write skew)
假如需要滿足約束x + y >= 0,初始時x = -3, y = 5,事務T1先讀x和y,然後事務T2讀x和y,接著事務T2將y改為3,然後提交,接著事務T1將x改為-5,然後提交。最終,x = -5,y = 3不滿足約束x + y >= 0。
三、基於鎖的隔離等級
鎖按照範圍、模式、期間來分門別類。按照範圍可以分為謂詞鎖(predicate)和行鎖(item),謂詞鎖會將滿足一個condition的所有行鎖住(包括滿足條件的不存在的行),行鎖只會鎖住特定的一行。按照模式可以分為讀鎖(read)和寫鎖(write),讀鎖和讀鎖可以共存,讀鎖和寫鎖互斥,寫鎖和寫鎖互斥(讀鎖和寫鎖的優先順序,寫鎖能否搶佔讀鎖)。按照期間可以分為短鎖(short)和長鎖(long),短鎖表示當要訪問資料時上鎖,讀寫完後馬上解鎖,長鎖表示當要訪問資料時加鎖,直到事務結束才解鎖。兩階段鎖(tow-phase lock)表示在事務剛開始時加上需要的讀鎖和寫鎖,直到事務結束時才將加上的所有鎖一次性釋放。兩階段鎖可以實現可序列化的隔離等級。基於鎖的隔離等級如下表所示:
- Degree 0允許dirty write
- Read Uncommitted允許dirty read
- Read Commited規避了dirty read/write,允許fuzzy read、loss of update、read skew以及write skew
- Cursor Stability規避了loss of update
- Repeatable Read規避了dirty read/write、fuzzy read、loss of update、read skew以及write skew,但會出現幻讀
- Serailizable規避了所有異常現象
四、Snapshot Isolation
MVCC維護了多個版本的資料,事務開啟的時候會給這個事務指定一個版本號碼StartTimeStamp,該事務的讀事務會讀到版本號碼不大於StartTimeStamp資料,讀操作不會阻塞,這樣的好處是讀和寫互不影響可以並發執行。當一個事務要提交時,資料庫會給這個事務指定一個CommitTimeStamp,假如有其他事務Tother的CommitTimeStampother在範圍[StartTimeStamp, CommitTimeStamp]並且Tother事務跟要提交的事務修改了同一行資料,那麼這個事務會abort掉,這稱作first-commiter-win原則(即樂觀鎖)。first-commiter-win原則保證了不會出現dirty write以及loss of update,一個事務內讀到的資料是同個版本的資料,保證了不會有fuzzy read、幻讀和read skew等現象,但其允許write skew。可以看出Snapshot Isolation跟Repeatable Read的嚴格程度是沒法比較的。
參考資料:
《A Critique of ANSI SQL Isolation Levels》
資料庫隔離等級