CS3402 Transactions and Concurrency Control
Transactions and Concurrency Control
事務(Transactions)
根據維基百科的定義,一個數據庫事務通常包含了一個序列的對數據庫的讀/寫操作。它的存在包含有以下兩個目的:1)為數據庫操作序列提供了一個從失敗中恢復到正常狀態的方法,同時提供了數據庫即使在異常狀態下仍能保持一致性的方法;2)當多個應用程序在並發訪問數據庫時,可以在這些應用程序之間提供一個隔離方法,以防止彼此的操作互相幹擾。簡單來講,事務的作用至少有兩個:保證數據一致性,以及對數據進行隔離。這麽說大家可能還不太好理解,我們還是舉個例子說明一下吧。
我們以A向B轉賬100塊錢為例,在一筆轉賬操作中,至少必須包含2個操作:
-
將A的賬戶余額扣除100塊錢(假設轉賬前A的賬戶余額大於100塊錢)
-
將B的賬戶余額增加100塊錢
如果在轉賬的過程中不使用事務,那麽有可能會出現在將A的賬戶扣除100塊錢之後,發生了不可預知的異常(比方說服務器宕機了),導致沒來得及將B的賬戶增加100塊錢,如此一來,數據庫就產生了數據不一致的情況,即A的賬戶扣了100塊錢,但是B的賬戶並沒有相應地增加100塊錢,也就是說有100塊錢“不翼而飛”了。而如果將這2個操作放在一個事務裏執行的話,由於事務中的操作要麽全部執行,要麽全部不執行,所以可以保證數據一致性。這就是在數據一致性要求比較高的場景下使用事務的好處。
事務的特性
事務的特性主要有4個:原子性,一致性,隔離性與持久性,也叫做ACID。
-
原子性,指的是一個事務必須被視為一個不可分割的最小工作單元,整個事務中的操作要麽全部提交成功,要麽全部失敗回滾,也就是說不可能只執行事務中的部分操作,這就是事務的原子性。
-
一致性,指的是事務應確保數據庫的狀態從一個一致狀態轉變為另一個一致狀態。以上述轉賬的例子為例,轉賬後A的賬戶減少100塊錢,B的賬戶增加100塊錢是滿足數據一致性的,事務可以保證事務成功提交之後數據庫轉化為這個狀態,如果事務失敗回滾了,則還是保持最初的一致性狀態,而不會出現上述的A的賬戶減少100塊錢,B的賬戶沒有變化的不一致的中間狀態。
-
隔離性,指的是多個事務並發執行時,一個事務的執行不應影響其他事務的執行。比如當A向B轉賬的過程中,B也可以向A轉賬,這2個事務互不影響,而且通常來講也是互不可見的(註意,是通常來講“不可見”,後續講到事務隔離級別的時候再詳述)。
-
持久性,指的是已被提交的事務對數據庫的修改應該被永久保存在數據庫中。這個比較好理解,就是說已成功提交的事務會被永久地保存下來。
事務的隔離級別
前文說到,事務具有隔離性,而且通常來講,不同事務之間是不可見的,然而現實中的事務隔離性並不都是不可見的,實際上,SQL標準定義了4種事務隔離級別:讀未提交,讀已提交,可重復讀,串行化,下文將逐一講解。
-
讀未提交,指的是事務中未提交的修改,對於其他事務而言是可見的,這是隔離性最低的一種級別了。在這種隔離級別下,會出現“臟讀”的情況。所謂“臟讀”指的是讀取到了其他事務未提交的數據。我們以2個事務同時進行為例,因為事務A可以讀到事務B的未提交的修改數據,假如說事務B在事務A結束之前因為發生異常而回滾了,那麽A讀到的事務B的未提交的數據就是“過期”的,如果事務A在這個“過期”數據上進行操作,那勢必會造成數據不一致的情況。因此這種隔離級別在實際中很少使用。
-
讀已提交,指的是一個事務開始時,只能看到其他已經提交的事務對數據所做的修改。這種隔離級別可以防止“臟讀”的問題出現。但是這種情況可能會出現“不可重復讀”的問題。所謂不可重復讀是指,事務A先後2次讀到的數據不一致。舉個例子,事務A先讀到小明的賬戶余額為100塊錢,然後再做了其他操作(假設這些操作沒有改變小明的余額),這個時候事務B將小明的賬戶扣了10塊錢,變成90塊錢了並提交了,由於事務A可以讀到事務B提交的修改數據,所以當事務A執行了其他操作後再讀取小明的余額時就變成90塊了,因此前後2次讀取的數據不一致,故出現了“不可重復讀”的問題。
-
可重復讀,指的是可以避免上述“不可重復讀”的情況出現,即它可以保證在同個事務中,先後讀到的同一行數據是一致的,然而這種隔離級別下會出現另一個問題,就是“幻象讀”。“幻象讀”指的是事務A讀取到了事務B新增的數據,因此出現了“幻行”。舉個例子,事務A一開始查詢到小明在1月份一共網購了100次,然後再進行其他操作(假設這些操作沒有改變小明的網購記錄數),然後事務B插入了一條小明新的網購記錄並提交了,接下來事務A再統計出小明的網購記錄,變成101次了,出現了“幻行”,也就是出現了“幻象讀”。
-
串性化,指的是強制事務串行執行,其可以避免“幻象讀”的問題出現,這是最嚴格的隔離級別了。因為串行化需要在發生競爭的數據上加鎖,所以並發性能不高,只有在對數據一致性要求非常高且並發度不高的情況下才會考慮使用這種隔離級別。
CS3402 Transactions and Concurrency Control