MySQL Next-Key Lock 加鎖范圍總結(jié)
前言
三篇文章分別通過實(shí)際操作,介紹了主鍵、非主鍵唯一索引、普通索引、普通字段四個(gè)方面介紹了加鎖的范圍。
本篇文章再做一個(gè)總結(jié)。
1data_locks
- select * from performance_schema.data_locks;
LOCK_MODE | LOCK_DATA | 鎖范圍 |
---|---|---|
X,REC_NOT_GAP | 15 | 15 那條數(shù)據(jù)的行鎖 |
X,GAP | 15 | 15 那條數(shù)據(jù)之前的間隙,不包含 15 |
X | 15 | 15 那條數(shù)據(jù)的間隙,包含 15 |
- LOCK_MODE = X 是前開后閉區(qū)間;
- X,GAP 是前開后開區(qū)間(間隙鎖);
- X,REC_NOT_GAP 行鎖。
這個(gè)單獨(dú)介紹,是希望我理解的沒有錯(cuò)誤,如果大佬看到了,錯(cuò)誤之處一定要幫忙指正出來。
2主鍵索引
- 加鎖時(shí),會先給表添加意向鎖,IX 或 IS;
- 加鎖是如果是多個(gè)范圍,是分開加了多個(gè)鎖,每個(gè)范圍都有鎖;(這個(gè)可以實(shí)踐下 id < 20 的情況)
- 主鍵等值查詢,數(shù)據(jù)存在時(shí),會對該主鍵索引的值加行鎖 X,REC_NOT_GAP;
- 主鍵等值查詢,數(shù)據(jù)不存在時(shí),會對查詢條件主鍵值所在的間隙添加間隙鎖 X,GAP;
- 主鍵等值查詢,范圍查詢時(shí)情況則比較復(fù)雜:
8.0.17 版本是前開后閉,而 8.0.18 版本及以后,修改為了前開后開區(qū)間;
臨界 <= 查詢時(shí),8.0.17 會鎖住下一個(gè) next-key 的前開后閉區(qū)間,而 8.0.18 及以后版本,修復(fù)了這個(gè) bug。
3非主鍵唯一索引
- 非主鍵唯一索引等值查詢,數(shù)據(jù)存在,for update 是會在主鍵加鎖的,而 for share 只有在走覆蓋索引的情況下,會僅在自己索引上加鎖;
- 非主鍵索引等值查詢,數(shù)據(jù)不存在,無論是否索引覆蓋,相當(dāng)于一個(gè)范圍查詢,僅僅會在非主鍵索引上加鎖,加的還是間隙鎖,前開后開區(qū)間;
- 在非主鍵唯一索引范圍查詢時(shí),不是覆蓋索引的時(shí)候,會對相應(yīng)的范圍加前開后閉區(qū)間,并且如果存在數(shù)據(jù),會對對應(yīng)的主鍵加行鎖;
- 在非主鍵唯一索引范圍查詢時(shí),如果是覆蓋索引時(shí),會對所有的后閉區(qū)間對應(yīng)的主鍵,加行鎖;
- 在非主鍵唯一索引加鎖時(shí),還是存在 next-key 鎖住下一個(gè)區(qū)間的 bug。
4普通索引
普通索引等值查詢,因?yàn)椴荒艽_定唯一性,所以即使定位到記錄,也是會向后查詢,直到查詢到不為該值的記錄,從而鎖定該值的區(qū)間;
普通索引的鎖也是加載該索引上的,如果涉及到存在的記錄,會對該主鍵加行鎖;
普通索引的范圍查詢,同樣出現(xiàn) next-key 查詢下一個(gè)區(qū)間的 bug。
5普通字段
普通字段查詢,會查詢?nèi)?,這里鎖的話就會鎖住主鍵的所有區(qū)間。
6總結(jié)
通過實(shí)際操作,最大的感受就是不能眼高手低,看書也好,看文章也罷,一定要實(shí)際操作。
紙上得來終覺淺。
本文轉(zhuǎn)載自微信公眾號「程序員小航」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系程序員小航公眾號。