MySQL InnoDB事務的隔離等級有四級,預設是“可重複讀”(REPEATABLE READ)。
未提交讀(READ UNCOMMITTED)。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料(髒讀)。
提交讀(READ COMMITTED)。本事務讀取到的是最新的資料(其他事務提交後的)。問題是,在同一個事務裡,前後兩次相同的SELECT會讀到不同的結果(不重複讀)。
可重複讀(REPEATABLE READ)預設層級。在同一個事務裡,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象(稍後解釋)。
序列化(SERIALIZABLE)。讀操作會隱式擷取共用鎖定,可以保證不同事務間的互斥。
四個層級逐漸增強,每個層級解決一個問題。
髒讀,最容易理解。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料。
不重複讀。解決了髒讀後,會遇到,同一個事務執行過程中,另外一個事務提交了新資料,因此本事務先後兩次讀到的資料結果會不一致。
幻讀。解決了不重複讀,保證了同一個事務裡,查詢的結果都是事務開始並且第一次查詢時的狀態(一致性)。但是,如果另一個事務同時提交了新資料,雖然本事務再次按照相同的條件尋找會得到相同的結果集,但是本事務指定更新時(看了後面的示範你就會知道),就會“驚奇的”發現了這些新資料,貌似之前讀到的資料是“鬼影”一樣的幻覺。
使用select for update 能夠對讀的記錄加鎖,避免幻讀
InnoDB通過Nextkey lock解決了當前讀時的幻讀問題
Innodb行鎖分為:
| 類型 |
說明 |
| Record Lock: |
在索引上對單行記錄加鎖. |
| Gap Lock: |
鎖定一個範圍的記錄,但不包括記錄本身.鎖加在未使用的空閑空間上,可能是兩個索引記錄之間,也可能是第一個索引記錄之前或最後一個索引之後的空間. |
| Next-Key Lock: |
行鎖與間隙鎖組合起來用就叫做Next-Key Lock。鎖定一個範圍,並且鎖定記錄本身。對於行的查詢,都是採用該方法,主要目的是解決幻讀的問題。 |