資料庫事務隔離級別

2022-08-28 22:42:23 字數 2970 閱讀 1348

一,事務的4個基本特徵

atomic(原子性): 

事務中包含的操作被看做乙個邏輯單元,這個邏輯單元中的操作要 

麼全部成功,要麼全部失敗。 

consistency(一致性): 

只有合法的資料可以被寫入資料庫,否則事務應該將其回滾到最初 

狀態。 

isolation(隔離性): 

事務允許多個使用者對同乙個資料進行併發訪問,而不破壞資料的正 

確性和完整性。同時,並行事務的修改必須與其他並行事務的修改 

相互獨立。 

durability(永續性): 

事務結束後,事務處理的結果必須能夠得到固化。 

在事務處理的acid屬性中,一致性是最基本的屬性,其它的三個屬性都為了保證一致性而存在的。

一致性,指的是資料處於一種有意義的狀態,這種狀態是語義上的而不是語法上的。最常見的例子是轉帳。例如從帳戶a轉一筆錢到帳戶b上,

如果帳戶a上的錢減少了,而帳戶b上的錢卻沒有增加,那麼我們認為此時資料處於不一致的狀態。

在資料庫實現中,在同乙個事務內部的一組操作必須全部執行成功(或者全部失敗),這就是事務處理的原子性。

為了實現原子性,需要通過日誌:將所有對資料的更新操作都寫入日誌,如果乙個事務中的一部分操作已經成功,但以後的操作,

由於斷電/系統崩潰/其它的軟硬體錯誤而無法繼續,則通過回溯日誌,將已經執行成功的操作撤銷,從而達到「全部操作失敗」的目的。

最常見的場景是,資料庫系統崩潰後重啟,此時資料庫處於不一致的狀態,必須先執行乙個crash recovery的過程:讀取日誌進行redo

(重演將所有已經執行成功但尚未寫入到磁碟的操作,保證永續性),再對所有到崩潰時尚未成功提交的事務進行undo(撤銷所有執

行了一部分但尚未提交的操作,保證原子性)。crash recovery結束後,資料庫恢復到一致性狀態,可以繼續被使用。

日誌的管理和重演是資料庫實現中最複雜的部分之一。如果涉及到並行處理和分布式系統(日誌的複製和重演是資料庫高可用性的基礎),會比上述場景還要複雜得多。

但是,原子性並不能完全保證一致性。在多個事務並行進行的情況下,即使保證了每乙個事務的原子性,仍然可能導致資料不一致的結果。例如,

事務1需要將100元轉入帳號a:先讀取帳號a的值,然後在這個值上加上100。但是,在這兩個操作之間,另乙個事務2修改了帳號a的值,為它

增加了100元。那麼最後的結果應該是a增加了200元。但事實上, 事務1最終完成後,帳號a只增加了100元,因為事務2的修改結果被事務1覆蓋掉了。

為了保證併發情況下的一致性,引入了隔離性,即保證每乙個事務能夠看到的資料總是一致的,就好象其它併發事務並不存在一樣。用術語來說

,就是多個事務併發執行後的狀態,和它們序列執行後的狀態是等價的。怎樣實現隔離性,已經有很多人回答過了,原則上無非是兩種型別的鎖:

一種是悲觀鎖,即當前事務將所有涉及操作的物件加鎖,操作完成後釋放給其它物件使用。為了盡可能提高效能,發明了各種粒度(資料庫級/表級/行級……)/各種性質

(共享鎖/排他鎖/共享意向鎖/排他意向鎖/共享排他意向鎖……)的鎖。為了解決死鎖問題,又發明了兩階段鎖協議/死鎖檢測等一系列的技術。

一種是樂觀鎖,即不同的事務可以同時看到同一物件(一般是資料行)的不同歷史版本。如果有兩個事務同時修改了同一資料行,那麼在較晚的事務提交時進行衝突檢測。

實現也有兩種,一種是通過日誌undo的方式來獲取資料行的歷史版本,一種是簡單地在記憶體中儲存同一資料行的多個歷史版本,通過時間戳來區分。

二,為什麼需要對事務併發控制

如果不對事務進行併發控制,我們看看資料庫併發操作是會有那些異常情形

lost update: 

兩個事務都同時更新一行資料,但是第二個事務卻中途失敗退出, 

導致對資料的兩個修改都失效了。

dirty reads: 

乙個事務開始讀取了某行資料,但是另外乙個事務已經更新了此數 

據但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作 

都被回滾。 

non-repeatable reads: 

乙個事務對同一行資料重複讀取兩次,但是卻得到了不同的結果。 

second lost updates problem: 

無法重複讀取的特例。有兩個併發事務同時讀取同一行資料,然後其 

中乙個對它進行修改提交,而另乙個也進行了修改提交。這就會造成 

第一次寫操作失效。 

phantom reads: 

事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查 

詢中未出現的資料(這裡並不要求兩次查詢的sql語句相同)。這是 

因為在兩次查詢過程中有另外乙個事務插入資料造成的。 

三, 資料庫的隔離級別

為了兼顧併發效率和異常控制,在標準sql規範中,定義了4個事務隔

離級別,(oracle和sqlserer對標準隔離級別有不同的實現 )

read uncommitted: 

直譯就是"讀未提交",意思就是即使乙個更新語句沒有提交,但是別 

的事務可以讀到這個改變.這是很不安全的. 

read committed: 

直譯就是"讀提交",意思就是語句提交以後即執行了commit以後 

別的事務就能讀到這個改變. 

repeatable read: 

直譯就是"可以重複讀",這是說在同乙個事務裡面先後執行同乙個 

查詢語句的時候,得到的結果是一樣的. 

serializable: 

直譯就是"序列化",意思是說這個事務執行的時候不允許別的事務 

併發執行. 

四,隔離級別對併發的控制

下表是各隔離級別對各種異常的控制能力:

ludr

nrrslu

prruny

yyyrc

nnyy

yrrnn

nnys

nnnn

n

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable,這四個級別可以逐個解決髒讀 不可重複讀 幻讀這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted rea...

資料庫事務隔離級別

資料庫事務的隔離級別有4個,由低到高依次為read uncommitted read committed repeatable read serializable 這四個級別可以逐個解決髒讀 不可重複讀 幻讀 這幾類問題。可能出現 不會出現 髒讀不可重複讀 幻讀read uncommitted re...