1、 ANSI SQL給出了四種标準的事務隔離級别:可序列化(Serializable)、可重複讀(Repeatable reads)、送出讀(Read committed)和未送出讀(Read uncommitted)。
還有一個Snapshot的概念。
2、 隔離級别隻會影響讀操作申請的共享鎖,而不會影響寫操作的互斥鎖。
3、 隔離級别影響讀事務的行為:
1) 否使用共享鎖,以哪種隔離級别來隔離。
2) 事務持有讀鎖的時間
3) 在有其他更新事務進行資料操作時,如何執行讀的操作。
l 被阻塞,等待其他事務釋放互斥鎖
l 讀取事務送出後的版本,該資料行在事務開始時存在
l 讀沒有送出的資料
下面介紹不同隔離級别下的差異
4、 隔離級别:ReadCommitted(意思是隻能讀到Commited的資料)
大多數資料庫預設的隔離模式(有說MySQL不是,不知指哪個存儲引擎)。在事務完成送出之前,其他事務看不到該事務的修改結果。但可能的是:如果一個事務A中讀2次資料。而在此中間,有另外事務B修改相關資料并送出,則在A的兩次讀中,值不一樣。是以也叫做不可重複讀。但確定的讀到的資料,一定是Commit的。
這裡還加上Snapshot後,行為有不同。
1) 如果Snapshot為OFF,讀操作申請共享鎖,阻塞其他事務的寫操作。一旦讀操作完成,釋放共享鎖。
2) 如果Snapshot為ON,讀操作時使用RowVersioning(這實際就是Snapshot的概念),就是有多副本,寫操作不阻塞讀操作,是以不會申請共享鎖,不會阻塞其他事務的寫操作。
5、 在ReadunCommited下
1) 讀操作不會申請SharedLock。是以讀操作不會阻塞寫操作。事務中的修改及時沒送出也會被其他事務可見,這樣會産生髒讀,如果事務失敗復原,則其他事務之前的到的資料則是髒資料。從性能上講,不會别别的事務提高太多,但是極其不安全。
6、 在Repeatablereads下
事務A讀取與搜尋條件相比對的若幹行。事務B以插入或删除行等方式來修改事務A的結果集,然後再送出。事務A再讀取時,卻發現資料發生了變化。造成了幻讀。(MySQL預設的隔離級别)。
另一種更好了解:事務在執行過程中可以看到其他事務已送出的新插入記錄,但不能看到其他事務已送出的對已有記錄的更新。
7、 在Serializable下
是最高的事務隔離級别,同時代價也花費最高,性能很低,一般很少使用,在該級别下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻讀。
在Snapshot隔離級别下,事務在修改任何資料之前,先将修改前的資料複制到tempdb,寫操作建立資料行的一個原始版本(Row Version)。後續其他事務的一切讀操作都去讀這個複制的行版本。在Snapshot隔離級别下,讀寫操作不會互相阻塞。使用行版本控制提高事務的并發性,但是有一個明顯的缺點,雖然使用者讀到的不是髒資料,但是資料可能正在被修改,很快就要過期。如果根據這個過期的資料做資料修改,可能會産生邏輯錯誤。
參考:
1、《資料庫的快照隔離級别(Snapshot Isolation)》https://www.cnblogs.com/ljhdo/p/5037033.html