1. 程式人生 > >資料庫事務ACID和四個隔離級別

資料庫事務ACID和四個隔離級別

在實際的業務場景中,併發讀寫引出了和事務控制的需求。優秀的事務處理能力是關係型資料庫(特別是oracle等商用RDBMS)相對於正當風口的NoSQL資料庫的一大亮點。但這也從另一方面說明了事務控制的複雜性——正因為過於複雜,大部分NoSQL都沒提供事務支援或只提供部分事務支援。

ACID

一個數據庫事務是"一個被視為單一的工作單元的操作序列"。一個良好的事務處理系統,必須具備四個標準特性:

原子性(Atomicity):一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要麼全部提交成功,要麼全部失敗回滾,對於一個事務來說,不可能只執行其中的一部分操作,這就是事務的原子性 一致性(Consistency)

:資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態。(在前面的例子中,一致性確保了,即使在執行第三、四條語句之間時系統崩潰,支票賬戶中也不會損失200美元,因為事務最終沒有提交,所以事務中所做的修改也不會儲存到資料庫中。) 隔離性(Isolation):通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的。 永續性(Durability):一旦事務提交,則其所做的修改不會永久儲存到資料庫。(此時即使系統崩潰,修改的資料也不會丟失。永續性是個有佔模糊的概念,因為實際上永續性也分很多不同的級別。有些永續性策略能夠提供非常強的安全保障,而有些則未必,而且不可能有能做到100%的永續性保證的策略。)

以上四個特性就是常說的ACID。其中,隔離性的四個級別是面試常考點。

隔離性的四個級別

READ UNCOMMITTED(未提交讀)

在READ UNCOMMITTED級別,事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以讀取未提交的資料,這也被稱為髒讀(Dirty Read)。這個級別會導致很多問題,從效能上來說,READ UNCOMMITTED不會比其他的級別好太多,但卻缺乏其他級別的很多好處,除非真的有非常必要的理由,在實際應用中一般很少使用。

READ COMMITTED(提交讀)

大多數資料庫系統的預設隔離級別都是READ COMMTTED(但MySQL不是)。READ COMMITTED滿足前面提到的隔離性的簡單定義:一個事務開始時,只能”看見”已經提交的事務所做的修改。換句話說,一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。這個級別有時候叫做不可重複讀(nonrepeatble read),因為兩次執行同樣的查詢,可能會得到不一樣的結果。

REPEATABLE READ(可重複讀)

REPEATABLE READ解決了髒讀的問題。該隔離級別保證了在同一個事務中多次讀取同樣記錄結果是一致的。但是理論上,可重複讀隔離級別還是無法解決另外一個幻讀(Phantom Read)的問題。所謂幻讀,指的是當某個事務在讀取某個範圍內的記錄時,另一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行(Phantom Row)。InnoDB和XtraDB儲存引擎通過多版本併發控制(MVCC,Multiversion Concurrency Control)解決了幻讀的問題。

SERIALIZABLE(序列化)

SERIALIZABLE是最高的隔離級別。它通過強制事務序列執行,避免了前面說的幻讀的問題。簡單來說,SERIALIZABLE會在讀取每一行資料都加鎖,所以可能導致大量的超時和鎖爭用問題。實際應用中也很少用到這個隔離級別,只有在非常需要確保資料的一致性而且可以接受沒有併發的情況下,才考慮採用該級別。

隔離級別的總結

打鉤說明該隔離級別還存在這種情況,打X代表該隔離級別已經解決了這種情況:

隔離級別 髒讀 不可重複讀 幻讀
讀未提交(Read uncommitted) Y Y Y
讀已提交(Read committed) X Y Y
可重複讀(Repeatable read) X X Y
可序列化(Serializable) X X X