天天看點

了解事務——原子性、一緻性、隔離性和持久性

事務是指對系統進行的一組操作,為了保證系統的完整性,事務需要具有ACID特性,具體如下:

1. 原子性(Atomic)

     一個事務包含多個操作,這些操作要麼全部執行,要麼全都不執行。實作事務的原子性,要支援復原操作,在某個操作失敗後,復原到事務執行之前的狀态。

     復原實際上是一個比較高層抽象的概念,大多數DB在實作事務時,是在事務操作的資料快照上進行的(比如,MVCC),并不修改實際的資料,如果有錯并不會送出,是以很自然的支援復原。

     而在其他支援簡單事務的系統中,不會在快照上更新,而直接操作實際資料。可以先預演一邊所有要執行的操作,如果失敗則這些操作不會被執行,通過這種方式很簡單的實作了原子性。

2. 一緻性(Consistency)

     一緻性是指事務使得系統從一個一緻的狀态轉換到另一個一緻狀态。事務的一緻性決定了一個系統設計和實作的複雜度。事務可以不同程度的一緻性:

      強一緻性:讀操作可以立即讀到送出的更新操作。

      弱一緻性:送出的更新操作,不一定立即會被讀操作讀到,此種情況會存在一個不一緻視窗,指的是讀操作可以讀到最新值的一段時間。

      最終一緻性:是弱一緻性的特例。事務更新一份資料,最終一緻性保證在沒有其他事務更新同樣的值的話,最終所有的事務都會讀到之前事務更新的最新值。如果沒有錯誤發生,不一緻視窗的大小依賴于:通信延遲,系統負載等。

     其他一緻性變體還有:

      單調一緻性:如果一個程序已經讀到一個值,那麼後續不會讀到更早的值。

      會話一緻性:保證用戶端和伺服器互動的會話過程中,讀操作可以讀到更新操作後的最新值。

3. 隔離性(Isolation)

     并發事務之間互相影響的程度,比如一個事務會不會讀取到另一個未送出的事務修改的資料。在事務并發操作時,可能出現的問題有:

      髒讀:事務A修改了一個資料,但未送出,事務B讀到了事務A未送出的更新結果,如果事務A送出失敗,事務B讀到的就是髒資料。

      不可重複讀:在同一個事務中,對于同一份資料讀取到的結果不一緻。比如,事務B在事務A送出前讀到的結果,和送出後讀到的結果可能不同。 不可重複讀出現的原因就是事務并發修改記錄,要避免這種情況,最簡單的方法就是對要修改的記錄加鎖,這回導緻鎖競争加劇,影響性能。另一種方法是通過MVCC可以在無鎖的情況下,避免不可重複讀。

      幻讀:在同一個事務中,同一個查詢多次傳回的結果不一緻。事務A新增了一條記錄,事務B在事務A送出前後各執行了一次查詢操作,發現後一次比前一次多了一條記錄。 幻讀是由于并發事務增加記錄導緻的,這個不能像不可重複讀通過記錄加鎖解決,因為對于新增的記錄根本無法加鎖。需要将事務串行化,才能避免幻讀。

     事務的隔離級别從低到高有:

      Read Uncommitted:最低的隔離級别,什麼都不需要做,一個事務可以讀到另一個事務未送出的結果。所有的并發事務問題都會發生。

      Read Committed:隻有在事務送出後,其更新結果才會被其他事務看見。 可以解決髒讀問題。

      Repeated Read:在一個事務中,對于同一份資料的讀取結果總是相同的,無論是否有其他事務對這份資料進行操作,以及這個事務是否送出。 可以解決髒讀、不可重複讀。

     Serialization:事務串行化執行,隔離級别最高,犧牲了系統的并發性。 可以解決并發事務的所有問題。

     通常,在工程實踐中,為了性能的考慮會對隔離性進行折中。

4. 持久性(Durability)

     事務送出後,對系統的影響是永久的。

繼續閱讀