ACID

      在計算機科學中,ACID(原子性、一致性、隔離性、持久性)是數據庫事務的一組屬性,目的是在發生錯誤、斷電等情況下保證有效性。在數據庫上下文中,滿足ACID屬性的數據庫操作序列(可以將其視爲數據上的單個邏輯操作)稱爲事務。例如,從一個銀行賬戶到另一個銀行賬戶的資金轉移,即使涉及多個變化,如借記一個賬戶和貸記另一個賬戶,也是一筆交易。1983年,Andreas Reuter和Theo Harder在Jim Gray的早期工作的基礎上創造了首字母縮略詞ACID,作爲原子性、一致性、隔離性和持久性的縮寫。這四個屬性描述了事務範型的主要保證,它影響了數據庫系統開發的許多方面。根據Gray和Reuter的說法,IMS早在1973年就支持ACID事務(儘管後來出現了ACID這個術語)。

Characteristics(特性)

Reuter和Harder定義的這四種屬性的特徵如下:

Atomicity:

事務通常由多條語句組成。原子性保證將每個事務視爲一個單獨的“單元”,這個單元要麼完全成功,要麼完全失敗:如果組成事務的任何語句沒有完成,整個事務就會失敗,數據庫也不會改變。原子系統必須保證在每種情況下的原子性,包括電源故障、錯誤和崩潰。原子性的保證可以防止對數據庫的更新只發生部分,這比完全拒絕整個系列操作請求可能會導致更大的問題。因此,其他數據庫客戶端無法觀察到事務正在進行中。在某個時刻,它還沒有發生,而在下一個時刻,它已經全部發生了(或者如果正在進行的事務被取消,則什麼也沒有發生)。原子事務的一個例子是一個貨幣從銀行a賬戶轉移到b賬戶。它包含兩個操作,從a賬戶中取出錢和把錢增加到b儲蓄賬戶,執行這些操作在一個原子事務確保數據庫仍然處於一致狀態,也就是說,錢既不失去也不增加如果這兩個操作失敗。

Consistency:

一致性確保事務只能將數據庫從一種有效狀態帶到另一種有效狀態,維護數據庫不變性:寫入數據庫的任何數據必須根據所有定義的規則(包括約束、級聯、觸發器以及它們的任何組合)有效。這可以防止非法事務破壞數據庫,但不能保證事務是正確的。引用完整性保證了主鍵-外鍵關係。

Isolation:


事務通常是併發執行的(例如,多個事務同時讀寫一個表)。隔離確保事務的併發執行使數據庫處於與順序執行事務時相同的狀態。隔離是併發控制的主要目標;根據使用的方法,不完整事務的影響甚至可能對其他事務不可見。

Durability:

持久性保證了一旦提交了事務,即使在系統故障(例如,斷電或崩潰)的情況下,它也將保持提交狀態。這通常意味着完成的事務(或它們的影響)被記錄在非易失性內存中如磁盤。


下面是例子:
下面的例子進一步說明了ACID的特性。在這些示例中,數據庫表有A和B兩列。完整性約束要求A中的值和B中的值之和必須爲100。下面的SQL代碼按照上面的描述創建一個表:

CREATE TABLE acidtest (A INTEGER, B INTEGER, CHECK (A + B = 100));

Atomicity

原子性是保證原子事務中的一系列數據庫操作要麼全部發生(一個成功的操作),要麼一個也不發生(一個不成功的操作)。這一系列的操作不能被分開,只能執行其中的一部分,這使得這一系列的操作“不可分割”。原子性的保證可以防止對數據庫的更新只發生部分,這比完全拒絕整個系列請求操作可能會導致更大的問題。換句話說,原子性意味着不可分割性和不可約性。或者,我們可以說一個邏輯事務可以由一個或多個(幾個)物理事務組成。除非並且直到所有的組件物理事務都被執行,否則邏輯事務不會在數據庫的影響下發生。假設我們的邏輯事務由資金由賬戶a轉移到賬戶b,這邏輯事務可能由幾個物理事務組成的第一個刪除賬戶的金額作爲第一物理事務,然後作爲第二事務,將上述錢存入賬戶b。我們不希望看到從賬戶a刪除之前它已轉入帳戶b,然後,除非並且直到兩個交易都發生了,並且金額已經轉移到賬戶B,否則轉移不會影響數據庫。

Consistency failure:

一致性是一個非常普遍的術語,它要求數據必須滿足所有驗證規則。在前面的示例中,驗證要求a + B = 100。必須檢查所有驗證規則以確保一致性。假設一個事務試圖在不改變B的情況下從a中減去10,因爲每個事務之後都會檢查一致性,所以在事務開始之前a + B = 100。如果事務成功地從A中刪除10,就會實現原子性。但是,驗證檢查將顯示a + B = 90,這與數據庫的規則不一致。整個事務必須取消,受影響的行必須回滾到它們的事務前狀態。如果存在其他約束、觸發器或級聯,則在提交事務之前,將以與上述相同的方式檢查每個更改操作。其他約束也可能出現類似的問題。我們可能要求A和B的數據類型都是整數。如果我們輸入,比如說,A的值13.5,那麼該事務將被取消,或者系統可能會以觸發器的形式發出警報(如果/當觸發器被寫入該效果時)。另一個例子是完整性約束,它不允許我們刪除一個表中的行,該表中的主鍵至少被其他表中的一個外鍵引用。

Isolation failure:

爲了演示隔離,我們假設兩個事務同時執行,每個事務都試圖修改相同的數據。其中一個必須等到另一個完成才能保持隔離。考慮兩個事務:T1轉移10從A到B, T2轉移20從B到A .
組合有四個動作:
1、T1從A減去10。
2、T1給B添加10 。
3、T2從B 減去20
4、T2給 A增加了20 .
如果按順序執行這些操作,保持隔離,儘管T2必須等待。考慮一下如果T1中途失效會發生什麼。數據庫消除了T1的影響,T2只看到有效的數據。
通過交錯事務,操作的實際順序可能是:
1、T1從a中減去10,
2、T2從B中減去20。
3、T1失效時,
4、T2已經修改了A;
如果不留下一個無效的數據庫,它就不能恢復到T1之前的值。這被稱爲寫-寫失敗,因爲兩個事務試圖寫入相同的數據字段。在典型的系統中,可以通過恢復到最後一個已知的良好狀態、取消失敗的事務T1和從良好狀態重新啓動中斷的事務T2來解決這個問題。

Durability failure:

考慮一個從a向b傳輸10的事務。首先,它從a中刪除10,然後向b添加10。此時,用戶被告知事務成功了。但是,更改仍然在磁盤緩衝區中排隊,等待提交到磁盤。此時電源失效,更改丟失。用戶假定(可以理解地)更改已經完成,事實上並沒有更新。

Implementation:

處理事務通常需要一系列操作,這些操作由於多種原因可能會失敗。例如,系統的磁盤驅動器可能已經沒有空間了,或者已經耗盡了分配的CPU時間。有兩種流行的技術:提前寫日誌 write-ahead logging和影子分頁shadow paging(在計算機科學中,影子分頁是一種在數據庫系統中提供原子性和持久性的技術。這裏的頁面指的是物理存儲單元,通常爲1到64 KiB)。在這兩種情況下,必須獲取要更新的所有信息上的鎖,並根據隔離級別,可能還需要讀取所有數據。在寫前日誌中,原子性是通過在更改數據庫之前將原始(未更改的)數據複製到日誌中來保證的。它允許數據庫在崩潰時返回一致的狀態。在影子分頁中,更新應用於數據庫的部分副本,並在事務提交時激活新副本。

Locking vs multiversioning:
 

      許多數據庫依賴於鎖定來提供ACID功能。鎖定意味着事務標記它訪問的數據,以便DBMS知道在第一個事務成功或失敗之前不允許其他事務修改它。在處理數據(包括讀取但未修改的數據)之前,必須始終獲取鎖。複雜的事務通常需要大量的鎖,從而導致大量的開銷,並阻塞其他事務。例如,如果用戶A正在運行一個事務,該事務必須讀取用戶B想要修改的一行數據,那麼用戶B必須等待,直到用戶A的事務完成。通常採用兩階段鎖來保證完全隔離。
      鎖定的一種替代方法是多版本併發控制,其中數據庫爲每個讀取事務提供另一個活動事務正在修改的數據的先前的、未修改的版本。這允許讀取器在不獲取鎖的情況下進行操作。寫事務不會阻塞讀事務,讀也不會阻塞寫。回到這個示例,當用戶A的事務請求用戶B正在修改的數據時,數據庫向A提供了用戶B開始事務時存在的數據版本。即使其他用戶正在更改數據,用戶A也可以獲得數據庫的一致視圖。一個實現,即快照隔離,放鬆了隔離屬性。

Distributed transactions:

保證跨分佈式數據庫的分佈式事務中的ACID屬性(其中沒有一個節點負責影響事務的所有數據)會帶來額外的複雜性。網絡連接可能失敗,或者一個節點可能成功完成其事務的一部分,然後由於另一個節點的失敗而需要回滾其更改。兩階段提交協議(不要與兩階段鎖定混淆)爲分佈式事務提供原子性,以確保事務中的每個參與者都同意是否應該提交事務。簡單地說,在第一階段,一個節點(協調器)詢問其他節點(參與者),只有當所有節點都回答準備就緒時,協調器纔會在第二階段將事務形式化。

發佈了16 篇原創文章 · 獲贊 7 · 訪問量 9743
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章