ACID屬性

詳解ACID屬性程序員

 

  計算機科學中ACID(Atomicity 原子性、Consistency 一致性、Isolation 隔離性、Durability 持久性)是一系列屬性。sql

一、Atomicity 原子性數據庫

  原子性要求每一個事物中的全部操做要麼所有完成,要麼就像所有沒有發生同樣:若是事物中的部分操做失敗了,則整個事物事物失敗了,結果就是數據庫中的狀態保持沒變。原子性系統必須保證在各類狀況下的原子性,包括主機斷電、主機發生了錯誤、主機奔潰。對外界來講,一個提交了的事物看起來(經過事物對數據庫產生的影響)是不可分的,一個失敗了的事物,對外界來講就好像什麼都沒有發生過同樣。併發

 

二、Consistency 一致性性能

  一致性確保了任何事物都會使數據庫從一種合法的狀態變爲另外一種合法的狀態。經過定義的各類規則,包括約束(constraints)、級聯(cascades)、觸發器(triggers)以及它們的組合來保證寫入數據庫的全部數據都必須是合法的。一致性並不能保證事物(程序)的正確性,換句話說事物的一致性並不必定如程序員所指望的那樣(這應該是由應用層代碼來負責的),它只能保證數據庫中的全部數據都不會違反定義好的規則,無論程序有沒有發生錯誤甚至是發生了任何錯誤都不會違反定義好的規則。spa

 

三、Isolation 隔離性操作系統

  隔離性保證了併發執行多個事物對系統的狀態的影響和串行化執行多個事物對系統的狀態的影響是同樣的。隔離性是併發控制的主要目標。 經過併發控制的方法,一個未完成的事物的影響對其餘事物是不可見的。日誌

 

四、Durability 持久性code

  持久性保證了一個事物一旦被提交之後,其狀態就保持不變,甚至是發生了主機斷電、奔潰、錯誤等。例如,在關係數據庫中,一旦一組 sql 語句被執行後,其結果就被永久保存(甚至事物剛被提交數據庫系統就發生了奔潰)。爲了主機抵禦斷電的風險,事物(或者是事物的結果)必須被記錄在永久性存儲中。事件

 

五、For Example

下面的例子進一步的說明了 ACID 屬性。在下面的例子中數據庫表有兩列,A 和 B 。數據完整性約束要求 A 列的值和 B 列的值之和必須等於 100 。下面的 SQL 語句建立了一張表,這張表知足上面的約束條件——A+B=100 。

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

原子性的反例

在數據庫系統中,原子性是 ACID 事物的四個屬性之一。在一個原子事物中,一系列的數據庫操做要麼所有發生,要麼所有不發生。這一系列的操做不能被相互分開,只執行部分操做。原子性要求這一系列操做不可分,原子性正如其名。原子性能夠保證數據庫不會出現部分更新的狀況。部分更新的狀況帶來的問題遠遠要比全部的操做所有失敗帶來的問題還要嚴重。原子性意味着不可分。

一致性的反例

一致性是個很是泛化的術語,它要求數據必須知足全部的合法規則。之前面的例子爲例,合法性規則是要求 A + B = 100 ,同時 A 和 B 還必須爲整數。對於 A 和 B 來講,其合法的範圍是能夠被推斷出來的。全部的合法規則必須都被檢查從而確保了事物的一致性。假設一個事物嘗試着從 A 中減去 10 而不修改 B 。由於每一個事物結束之後都會進行一致性檢查,在事物開始以前數據庫就知道 A + B = 100 。若是事物成功的從 A 中減去 10 ,原子性就生效了。然而,有效性校驗會發現 A + B = 90 ,這與數據庫的約束規則不一致。整個事物必須被取消,被影響到的行回滾到執行事物以前的狀態。若是還有其餘約束、觸發器、級聯,每個獨立改變的操做在事物被提交以前必須像前面同樣進行一致性檢查。

違反隔離性

爲了演示隔離性,咱們假設兩個事物在同時修改同一塊數據。爲了維護隔離性,其中一個事物必須等到另一個事物完成之後才能執行。考慮下面的兩個事物, T1 從 A 中轉出 10 到 B 。T2 從 B 中轉出 10 到 A 。能夠分析出共有四個操做: 
一、T1 從 A 中減去 10 。 
二、T1 給 B 中加上 10 。 
三、T2 從 B 中減去 10 。 
四、T2 給 A 中加上 10 。 
若是這些操做按照上面的順序執行,就能夠達到隔離性,儘管 T2 必須等待 T1 先執行。若是 T1 中途失敗了,數據庫系統會消除掉 T1 對數據庫所產生的影響,T2 看到的仍然是合法的數據。

因爲兩個事物可能交錯執行,這幾個操做的實際執行順序多是:

  • T1 從 A 中減去 10 。
  • T2 從 B 中減去 10 。
  • T2 給 A 增長 10 。
  • T1 給 B 增長 10 。

再次假設,T1 中途失敗了,將會發生什麼。若是 T1 在第四步:T1 給 B 增長 10 時失敗了,而此時 T2 已經修改完了 A 和 B;被改變的數據沒法恢復到 T1 執行以前的狀態,致使了數據庫產生了不合法的狀態。 這就是有名的 「write-write failure」 失敗,因爲兩個事物嘗試同時修改同一個數據塊。 在一個典型的系統中,這個問題能夠解決。經過取消失敗的事物 T1 ,從而使數據庫恢復到上次的合法狀態,而後從新開始執行被中斷的事物 T2 。

違反持久性

假設一個事物從 A 中減去 10 加到 B 中。首先,事物會從 A 中減去 10 ,而後再在 B 中加上 10 。 在此時,執行事物的程序會告訴用戶,事物已經成功執行了。而後,此時這些改變的數據仍然還在磁盤緩衝區中排隊等待寫入磁盤中。若是這時主機發生斷電,數據庫中全部的改變就會丟失。用戶還覺得全部的改變都已經持久化到磁盤中了。

實現

處理一個事物一般須要一系列的操做,任意一個操做失敗了都會致使整個事物的失敗,所以,形成事物失敗的緣由有好多個。例如,系統的磁盤已經滿了,再沒有空間了,或者是事物已經用光了操做系統分配給它的 CPU 時間片。有兩種你們都很熟悉的流行技術:預寫式日誌記錄和影子分頁。這兩種技術中,必需要在將被更新的全部信息上獲取鎖。獲取的鎖依賴事物的隔離級別,有可能全部的數據僅僅是被讀取,也須要獲取鎖。在預寫式日誌記錄技術中,在改變數據庫以前經過複製原始的(未改變的)數據到日誌記錄中來保證原子性。有了日誌記錄就可使數據庫恢復到發生奔潰事件以前的一致性狀態。在影子分頁技術中,更新被應用到數據庫的部分拷貝中,當數據庫事物提交時,新的拷貝才被激活了。

好多數據庫依賴鎖來實現 ACID 能力。鎖意味着事物在其須要訪問的數據上打個標記,這樣一來數據庫管理系統就會知道這些數據在該事物完成(事物成功或失敗)以前不容許其餘事物修改這些被打了標記的數據。鎖在數據被處理以前必須獲取到,也包括處理那些只會被讀取但不會被修改的數據以前也要獲取鎖。非日常事物一般須要大量鎖,致使了不小的性能開銷同時也阻塞了其餘事物。例如,用戶 A 正在執行一個事物,須要讀取某一行數據而這時另一個用戶 B 正在修改這一行數據。用戶 B 必須等到用戶 A 的事物完全完成。一般能夠經過兩個階段鎖來保證全隔離性。

相關文章
相關標籤/搜索