在資料庫的處理過程中常會遇到一些併發的情況,因而會導致這樣或那樣的問題。而資料庫的事務隔離級別就是用來應對這些問題,針對不同的場景使資料的併發操作和讀取滿足一定規則。
通常我們會遇到以下幾種常見問題
資料丟失發生在兩個程序同時操作同一條資料時,比如process a 更新內容為「icecream」,process b更新內容為「milk」,再次查詢的時候,process a更新的資料就可能丟失了。因為兩個程序操作的是同一條資料。
髒讀發生在讀取資料時,讀取的資料不是正確的。比如process a做了一次update操作,更新了**為110,但是還沒有commit事務,process b讀取了這條資料的**,但是之後process a把這條事務rollback了。使**變回了原來的100,那麼剛才process b就發生了髒讀。
不可重複讀發生在乙個process讀取相同的資料時(比如相同的where條件),兩次讀取的資料不一致。這種情況發生在process a在第一和第二次讀取資料之間,process b把process a讀取的資料改變了。因而process a第二次讀取資料時,資料的值就會前後不一致了。
幻讀指你兩次相同的查詢可能得到的結果數不同,因而叫幻讀。比如process a的乙個事務內做乙個select查詢操作(帶上where條件),第一次select返回資料100條。process b之後更新了和process a之前select語句相同的where條件的資料,當process a再次做跟第一次相同的select時發現資料之後109條了,此時process a的事務才完成。原因就是process b的更新可能使資料從乙個date page移動到另外的date page(資料存放的底層結構)。
因而也就有了幾種事務隔離級別的產生。在講事務隔離級別之前,我們還要引入下不同的併發模型。按型別通常分兩種:樂觀併發(optimistic concurrency)和悲觀併發(pessimistic concurrency)
悲觀併發指在資料讀取時對資料加鎖,如果其他process想要對改資料做更新必須等到讀取的鎖釋放才能做更新。如果對資料做更新時也會加鎖,如果其他process想要對資料讀取和更新都必須要等到該鎖釋放。
樂觀併發指在對資料讀取時,不會影響其他process對相同資料做更新。在對資料做更新時,也不會影響其他process對資料的讀取。這種方式的實現呢,主要是考duplicate一條相同的資料使他們的版本號不同,然後讀取和更新分別在不同版本的資料上,在合適的時候commit和去掉舊的資料。
哎呀媽呀,急死俺了,終於到中心點了。sql server 2008支援5種事務隔離級別,分別是read uncommitted, read committed,repeatable read,snapshot,serializable。
這種事務隔離級別允許你發生除了資料丟失之外的其他問題。因為通常情況下資料讀取會使用鎖(共享鎖share lock),就是說讀一條資料會對該資料加個鎖,導致其他process不能更新該條資料做更新,但是可以讀取。而寫鎖通常會使用排他鎖(exclusive lock),就是說一條資料在被更新時,其他process能讀取但不能更新這條資料。這種事務隔離級別通常可以用在對資料的準確性上要求不是很高的地方(比如市場趨勢報告等),或者對資料庫插的吞吐量有要求的地方。因為維護對資料的鎖需要一定的開銷,因而會導致資料處理的能力降低。
這種事務隔離級別也是通常資料庫預設的資料隔離級別。允許process能讀取已被commit的資料。它還分read committed(locking)和read committed(snapshot). read committed(locking)就是使用上面提到的悲觀併發模型,read committed(snapshot)就是使用上面提到的樂觀併發模型。
在這種事務隔離級別下,不允許發生不可重複讀(non-repeatable read)的情況。但是允許幻讀。意思就是說不允許讀取的資料列的內容發生改變,但是允許讀取的資料在data page的位置發生改變(就是除了查詢的資料列之外的資料是可以被改變的)。相應的開銷包括共享鎖(share lock)和排他鎖(exclusive lock).
snapshot的事務隔離級別下,事務的處理和read committed(snapshot)的情況和方式基本是一致的。同時snapshot又和serializable的方式又有些共同的地方。不過在處理併發的情況下會有些特別的地方。
比如以下兩個事務同時執行:
process a (transaction a)
use pubs
set transaction isolation level snapshot
declare @price money
begin tran
select @price = price from titles where title_id = 『bu1032』
update titles set price = @price where title_id = 『ps7777』
commit tran
process b (transaction b)
use pubs
set transaction isolation level snapshot
declare @price money
begin tran
select @price = price from titles where title_id = 『ps7777』
update titles set price = @price where title_id = 『bu1032』
commit tran
在兩條同時發生的事務中,最後』ps7777』和』bu1032』的值會發生交換。我個人的理解是,資料庫會分別使兩條事務的執行環境分離。然後兩個執行緒使用cpu時間片輪轉的方式,分別切換著執行。因而產生的資料結果就使兩條資料的值進行了交換。
是要求最高的事務分離級別,之前我們提到的問題它都不允許發生。相應的開銷也是很大的。除了對讀取和操作的資料加鎖之外,還會對讀取的或更新的where條件的資料進行加鎖(即使資料不存在,使用key-range lock)。操作相同where條件的資料,事務執行的順序按照process獲得鎖的先後來執行。
事務隔離級別的理解
資料庫事務的隔離級別有4種,由低到高分別為read uncommitted read committed repeatable read serializable 而且,在事務的併發操作中可能會出現髒讀,不可重複讀,幻讀。下面通過事例一一闡述它們的概念與聯絡。read uncommitted 讀未提...
事務隔離級別的個人理解
事務隔離級別是指若干個併發的事務之間的隔離程度。1.read uncommitted 讀未提交,可能出現髒讀 不可從復讀 幻讀 髒讀相對於其他事務 b 來說 本事務 a 做了修改,髒讀是讀到了錯誤資料 a修改 b讀取 a start a update b start b read b end a r...
MySQL事務隔離級別的型別
1.事務隔離級別型別以及序列化介紹 事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每乙個使用者開啟的事務,不能被其他事務的運算元據所干擾,多個併發事務之間要相互隔離。在併發下事務會容易出現一些問題 髒讀 乙個事務開始讀取了某行資料,另外乙個事務已經更新了此資料但沒有能夠及時提交。這是相當危險的,...