資料庫事務與鎖的關係
原文:http://blog.csdn.net/dreamwbt/article/details/53371687
概述:資料庫操作具有四個特性:原子性,隔離性,永續性,一致性。當多個執行緒操作同一個資料的時候根據不同執行緒或者事務的動作和時機的不同會出現不同的併發問題,比如髒讀,不可重讀,幻讀,丟失更新等。
資料庫事務就是具有上述四個特性的一種資料庫操作邏輯,而解決不同事務的併發問題的時候就需要根據上述不同的問題設定不同的隔離級別,而不同的隔離級別底層用的就是不同的資料庫鎖機制,比如行鎖,表鎖,頁鎖,悲觀鎖,樂觀鎖等
本文主要依據InnoDB引擎來理解四個事務隔離級別,以及髒讀、不重複讀、幻讀的理解。
有四級,預設是“可重複讀”(REPEATABLE READ)。
· 未提交讀(READUNCOMMITTED)。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料(髒讀)。
· 提交讀(READCOMMITTED)。本事務讀取到的是最新的資料(其他事務提交後的)。問題是,在同一個事務裡,前後兩次相同的SELECT會讀到不同的結果(不重複讀)。
· 可重複讀(REPEATABLEREAD)。在同一個事務裡,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(稍後解釋)。
· 序列化(SERIALIZABLE)。讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。
四個級別逐漸增強,每個級別解決一個問題。
· 髒讀,最容易理解。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料。
· 不重複讀。解決了髒讀後,會遇到,同一個事務執行過程中,另外一個事務提交了新資料,因此本事務先後兩次讀到的資料結果會不一致。
· 幻讀。解決了不重複讀,保證了同一個事務裡,查詢的結果都是事務開始時的狀態(一致性)。但是,如果另一個事務同時提交了新資料,本事務再更新時,就會“驚奇的”發現了這些新資料,貌似之前讀到的資料是
事務的四種隔離級別
在資料庫操作中,為了有效保證併發讀取資料的正確性,提出的事務隔離級別。我們的資料庫鎖,也是為了構建這些隔離級別存在的。
隔離級別 | 髒讀(Dirty Read) | 不可重複讀(NonRepeatable Read) | 幻讀(Phantom Read) |
---|---|---|---|
未提交讀(Read uncommitted) | 可能 | 可能 | 可能 |
已提交讀(Read committed) | 不可能 | 可能 | 可能 |
可重複讀(Repeatable read) | 不可能 | 不可能 | 可能 |
可序列化(Serializable ) | 不可能 | 不可能 | 不可能 |
- 未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的資料
- 提交讀(Read Committed):只能讀取到已經提交的資料。Oracle等多數資料庫預設都是該級別 (不重複讀)
- 可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB預設級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀
- 序列讀(Serializable):完全序列化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞