事務是數據庫系統中的重要概念,瞭解這一律念是以正確的方式開發和數據庫交互的應用程序的前提。可是不少同窗對於事務的認識相對片面和膚淺,僅僅把它等同於ACID,不瞭解數據庫系統引入事務的真正動機,ACID對於事務意味着什麼以及最重要的:數據庫系統是如何保證事務的ACID特性的?java
轉帳是生活中常見的操做,好比從A帳戶轉帳100元到B帳號。站在用戶角度而言,這是一個邏輯上的單一操做,然而在數據庫系統中,至少會分紅兩個步驟來完成:mysql
在這個過程當中可能會出現如下問題:sql
爲了便於解決這些問題,須要引入數據庫事務的概念。數據庫
定義:數據庫事務是構成單一邏輯工做單元的操做集合
一個典型的數據庫事務以下所示併發
BEGIN TRANSACTION //事務開始 SQL1 SQL2 COMMIT/ROLLBACK //事務提交或回滾
關於事務的定義有幾點須要解釋下:mvc
對於上面的轉帳例子,能夠將轉帳相關的全部操做包含在一個事務中ide
BEGIN TRANSACTION A帳戶減小100元 B帳戶增長100元 COMMIT
事務使系統可以更方便的進行故障恢復以及併發控制,從而保證數據庫狀態的一致性。性能
原子性(Atomicity):事務中的全部操做做爲一個總體像原子同樣不可分割,要麼所有成功,要麼所有失敗。3d
一致性(Consistency):事務的執行結果必須使數據庫從一個一致性狀態到另外一個一致性狀態。一致性狀態是指:1.系統的狀態知足數據的完整性約束(主碼,參照完整性,check約束等) 2.系統的狀態反應數據庫本應描述的現實世界的真實狀態,好比轉帳先後兩個帳戶的金額總和應該保持不變。日誌
隔離性(Isolation):併發執行的事務不會相互影響,其對數據庫的影響和它們串行執行時同樣。好比多個用戶同時往一個帳戶轉帳,最後帳戶的結果應該和他們按前後次序轉帳的結果同樣。
持久性(Durability):事務一旦提交,其對數據庫的更新就是持久的。任何事務或系統故障都不會致使數據丟失。
在事務的ACID特性中,C即一致性是事務的根本追求,而對數據一致性的破壞主要來自兩個方面
數據庫系統是經過併發控制技術和日誌恢復技術來避免這種狀況發生的。
併發控制技術保證了事務的隔離性,使數據庫的一致性狀態不會由於併發執行的操做被破壞。
日誌恢復技術保證了事務的原子性,使一致性狀態不會因事務或系統故障被破壞。同時使已提交的對數據庫的修改不會因系統崩潰而丟失,保證了事務的持久性。
在講解併發控制技術前,先簡單介紹下數據庫常見的併發異常。
在事務1對數據A的回滾,致使事務2對A的已提交修改也被回滾了。
事務1和事務2讀取A的值都爲10,事務2先將A加上10並提交修改,以後事務2將A減小10並提交修改,A的值最後爲,致使事務2對A的修改好像丟失了同樣
在事務1對A的處理過程當中,事務2讀取了A的值,但以後事務1回滾,致使事務2讀取的A是未提交的髒數據。
因爲事務2對A的已提交修改,事務1先後兩次讀取的結果不一致。
事務1查詢A5的數據,因爲事務2插入了一條A=4的數據,致使事務1兩次查詢獲得的結果不同
事務的隔離級別越低,可能出現的併發異常越多,可是一般而言系統能提供的併發能力越強。
不一樣的隔離級別與可能的併發異常的對應狀況以下表所示,有一點須要強調,這種對應關係只是理論上的,對於特定的數據庫實現不必定準確,好比mysql
的Innodb存儲引擎經過Next-Key Locking技術在可重複讀級別就消除了幻讀的可能。
全部事務隔離級別都不容許出現髒寫,而串行化能夠避免全部可能出現的併發異常,可是會極大的下降系統的併發處理能力。
併發控制技術是實現事務隔離性以及不一樣隔離級別的關鍵,實現方式有不少,按照其對可能衝突的操做採起的不一樣策略能夠分爲樂觀併發控制和悲觀併發控制兩大類。
核心思想:對於併發可能衝突的操做,好比讀-寫,寫-讀,寫-寫,經過鎖使它們互斥執行。
鎖一般分爲共享鎖和排他鎖兩種類型
基於鎖的併發控制流程:
可能出現的問題:
對於可能發生衝突的併發操做,鎖使它們由並行變爲串行執行,是一種悲觀的併發控制。
核心思想:對於併發可能衝突的操做,基於時間戳排序規則選定某事務繼續執行,其餘事務回滾。
系統會在每一個事務開始時賦予其一個時間戳,這個時間戳能夠是系統時鐘也能夠是一個不斷累加的計數器值,當事務回滾時會爲其賦予一個新的時間戳,先開始的事務時間戳小於後開始事務的時間戳。
每個數據項Q有兩個時間戳相關的字段:
W-timestamp(Q):成功執行write(Q)的全部事務的最大時間戳
R-timestamp(Q):成功執行read(Q)的全部事務的最大時間戳
時間戳排序規則以下:
基於時間戳排序和基於鎖實現的本質同樣:對於可能衝突的併發操做,以串行的方式取代併發執行,於是它也是一種悲觀併發控制。它們的區別主要有兩點:
核心思想:事務對數據的更新首先在本身的工做空間進行,等到要寫回數據庫時才進行有效性檢查,對不符合要求的事務進行回滾。
基於有效性檢查的事務執行過程會被分爲三個階段:
有效性檢查一般也是經過對事務的時間戳進行比較完成的,不過和基於時間戳排序的規則不同。
該方法容許可能衝突的操做併發執行,由於每一個事務操做的都是本身工做空間的局部變量,直到有效性檢查階段發現了衝突纔回滾。於是這是一種樂觀的併發策略。
快照隔離是多版本併發控制(mvcc)的一種實現方式。
其核心思想是:數據庫爲每一個數據項維護多個版本(快照),每一個事務只對屬於本身的私有快照進行更新,在事務真正提交前進行有效性檢查,使得事務正常提交更新或者失敗回滾。
因爲快照隔離致使事務看不到其餘事務對數據項的更新,爲了不出現丟失更新問題,能夠採用如下兩種方案避免:
事務間可能衝突的操做經過數據項的不一樣版本的快照相互隔離,到真正要寫入數據庫時才進行衝突檢測。於是這也是一種樂觀併發控制。
以上只是對常見的幾種併發控制技術進行了介紹,不涉及特別複雜的原理的講解。之因此這麼作一是要真的把原理和實現細節講清楚須要涉及的東西太多,篇幅太長,從做者和讀者角度而言都不是一件輕鬆的事,因此只對其實現的核心思想和實現要點進行了簡單的介紹,其餘部分就一筆帶過了。二是併發控制的實現的方式太過多樣,基於封鎖的實現就有不少變體,mvcc多版本併發控制的實現方式就更是多樣,並且不少時候會和其餘併發控制方式好比封鎖的方式結合起來使用。
數據庫運行過程當中可能會出現故障,這些故障包括事務故障和系統故障兩大類
這些故障可能會對事務和數據庫狀態形成破壞,於是必須提供一種技術來對各類故障進行恢復,保證數據庫一致性,事務的原子性以及持久性。數據庫一般以日誌的方式記錄數據庫的操做從而在故障時進行恢復,於是能夠稱之爲日誌恢復技術。
事務的執行過程能夠簡化以下:
因爲數據庫存在當即修改和延遲修改,因此在事務執行過程當中可能存在如下狀況:
<T,X,V1,V2>
:描述一次數據庫寫操做,T是執行寫操做的事務的惟一標識,X是要寫的數據項,V1是數據項的舊值,V2是數據項的新值。<T,X,V1>
:對數據庫寫操做的撤銷操做,將事務T的X數據項恢復爲舊值V1。在事務恢復階段插入。<T start>
: 事務T開始<T commit>
: 事務T提交<T abort>
: 事務T停止關於日誌,有如下兩條規則
<T abort>
記錄。事務正常回滾/因事務故障停止將進行redo
系統從崩潰中恢復時將先進行redo再進行undo。
如下事務將進行undo:日誌中只包括<T start>
記錄,但既不包括<T commit>
記錄也不包括<T abort>
記錄.
如下事務將進行redo:日誌中包括<T start>
記錄,也包括<T commit>
記錄或<T abort>
記錄。
假設系統從崩潰中恢復時日誌記錄以下
<T0 start> <T0,A,1000,950> <T0,B,2000,2050> <T0 commit> <T1 start> <T1,C,700,600>
因爲T0既有start記錄又有commit記錄,將會對事務T0進行重作,執行相應的redo操做。
因爲T1只有start記錄,將會對T1進行撤銷,執行相應的undo操做,撤銷完畢將寫入一條abort記錄。
<T,X,V1,V2>
的記錄,將舊值V1寫入數據項X中。<T,X,V1>
,表示將數據項恢復成舊值V1,<T start>
日誌記錄,就中止繼續掃描,並往日誌中寫一個<T abort>
日誌記錄。檢查點是形如<checkpoint L>
的特殊的日誌記錄,L是寫入檢查點記錄時還未提交的事務的集合,系統保證在檢查點以前已經提交的事務對數據庫的修改已經寫入磁盤,不須要進行redo。檢查點能夠加快恢復的過程。
系統奔潰時的恢復過程分爲兩個階段:重作階段和撤銷階段。
重作階段:
<T,X,V1,V2>
的更新記錄或<T,X,V>
的補償撤銷記錄,就重作該操做。<T start>
記錄,就把T加入到undo-list中。<T abort>
或<T commit>
記錄,就把T從undo-list中去除。撤銷階段:
<T start>
記錄,就寫入一條<T abort>
記錄,4.undo-list爲空,則撤銷階段結束
總結:先將日誌記錄中全部事務的更新按順序重作一遍,在針對須要撤銷的事務按相反的順序執行其更新操做的撤銷操做。
恢復前的日誌以下,寫入最後一條日誌記錄後系統崩潰
<T0 start> <T0,B,2000,2050> <T2 commit> <T1 start> <checkpoint {T0,T1}> //以前T2已經commit,故不用重作 <T1,C,700,600> <T1 commit> <T2 start> <T2,A,500,400> <T0,B,2000> <T0 abort> //T0回滾完成,插入該記錄後系統崩潰
事務是數據庫系統進行併發控制的基本單位,是數據庫系統進行故障恢復的基本單位,從而也是保持數據庫狀態一致性的基本單位。ACID是事務的基本特性,數據庫系統是經過併發控制技術和日誌恢復技術來對事務的ACID進行保證的,從而能夠獲得以下的關於數據庫事務的概念體系結構。