什麼是數據庫ACID?

 事務在當今的企業系統無處不在,即使在高併發環境下也可以提供數據的完整性。一個事務是一個只包含所有讀/寫操作成功的集合。如下圖:

一個事務本質上有四個特點ACID:

  1. Atomicity原子性
  2. Consistency一致性
  3. Isolation隔離性
  4. Durability耐久性

原子性

原子性任務是一個獨立的操作單元,是一種要麼全部是,要麼全部不是的原子單位性的操作。

一致性

一個事務可以封裝狀態改變(除非它是一個只讀的)。事務必須始終保持系統處於一致的狀態,不管在任何給定的時間併發事務有多少。

一致性有下面特點:

  • 如果一個操作觸發輔助操作(級聯,觸發器),這些也必須成功,否則交易失敗。
  • 如果系統是由多個節點組成,一致性規定所有的變化必須傳播到所有節點(多主複製)。如果從站節點是異步更新,那麼我們打破一致性規則,系統成爲“最終一致性”。
  • 一個事務是數據狀態的切換,因此,如果事務是併發多個,系統也必須如同串行事務一樣操作。

在現實中,事務系統遭遇併發請求時,這種串行化是有成本的, Amdahl法則描述如下:它是描述序列串行執行和併發之間的關係。

“一個程序在並行計算情況下使用多個處理器所能提升的速度是由這個程序中串行執行部分的時間決定的。”

大多數數據庫管理系統選擇(默認情況下)是放寬一致性,以達到更好的併發性。

隔離性

事務是併發控制機制,他們交錯使用時也能提供一致性。隔離讓我們隱藏來自外部世界未提交的狀態變化,一個失敗的事務不應該破壞系統的狀態。隔離是通過用悲觀或樂觀鎖機制實現的。

 

耐久性

一個成功的事務將永久性地改變系統的狀態,所以在它結束之前,所有導致狀態的變化都記錄在一個持久的事務日誌中。如果我們的系統突然受到系統崩潰或斷電,那麼所有未完成已提交的事務可能會重演。

 

儘管一些數據庫系統提供多版本併發控制 MVCC, 他們的併發控制都是通過鎖完成,因此,鎖會增加執行的串行性,影響併發性。

 

SQL標準規定了四個隔離水平:

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPETABLE_READ
  • SERIALIZABLE
隔離級別 髒讀 非重複讀 Phantom read
READ_UNCOMMITTED allowed allowed allowed
READ_COMMITTED prevented allowed allowed
REPETABLE_READ prevented prevented allowed
SERIALIZABLE prevented prevented prevented

 

髒讀

髒讀

髒讀發生在:當一個事務允許讀取一個被其他事務改變但是未提交的狀態時,這是因爲並沒有鎖阻止讀取,如上圖,你看到第二個事務讀取了一個並不一致的值,不一致的意思是,這個值是無效的,因爲修改這個值的第一個事務已經回滾,也就是說,第一個事務修改了這個值,但是未提交確認,卻被第二個事務讀取,第一個事務又放棄修改,悔棋了,而第二個事務就得到一個髒數據。

非重複讀

非重複讀

反覆讀同一個數據卻得到不同的結果,這是因爲在反覆幾次讀取的過程中,數據被修改了,這就導致我們使用了stale數據,這可以通過一個共享讀鎖來避免。這是隔離級別READ_COMMITTED會導致可重複讀的原因。設置共享讀鎖也就是隔離級別提高到REPETABLE_READ。

Phantom 讀

幻象讀

當第二個事務插入一行記錄,而正好之前第一個事務查詢了應該包含這個新紀錄的數據,那麼這個查詢事務的結果裏肯定沒有包含這個剛剛新插入的數據,這時幻影讀發生了,通過變化鎖和predicate locking避免。

下圖是主流數據庫的默認隔離級別:

Database Default isolation Level
Oracle READ_COMMITTED
MySQL REPETABLE_READ
Microsoft SQL Server READ_COMMITTED
PostgreSQL READ_COMMITTED
DB2 CURSOR STABILITY (a.k.a READ_COMMITTED)

READ_COMMITED 是正確的選擇,因爲SERIALIZABLE雖然能在不同事務發生時避免stale數據,也就是避免上述丟失剛剛修改的數據,但是性能是最低的,因爲是一種最大化的串行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章