MySQL 是怎么加行級鎖的?為什么一會是 next-key 鎖,一會是間隙鎖,一會又是記錄鎖?( 四 )

事務 A 加鎖變化過程如下:

  1. 最開始要找的第一行是 id = 20 , 由于查詢該記錄不是一個等值查詢(不是大于等于條件查詢),所以對該主鍵索引加的是范圍為 (15, 20] 的 next-key 鎖;
  2. 由于是范圍查找,就會繼續往后找存在的記錄,雖然我們看見表中最后一條記錄是 id = 20 的記錄,但是實際在 Innodb 存儲引擎中,會用一個特殊的記錄來標識最后一條記錄,該特殊的記錄的名字叫 supremum pseudo-record,所以掃描第二行的時候 , 也就掃描到了這個特殊記錄的時候,會對該主鍵索引加的是范圍為 (20, +∞] 的 next-key 鎖 。
  3. 停止掃描 。
可以得知,事務 A 在主鍵索引上加了兩個 X 型 的 next-key 鎖:
MySQL 是怎么加行級鎖的?為什么一會是 next-key 鎖,一會是間隙鎖,一會又是記錄鎖?

文章插圖
  • 在 id = 20 這條記錄的主鍵索引上 , 加了范圍為 (15, 20] 的 next-key 鎖,意味著其他事務即無法更新或者刪除 id = 20 的記錄,同時無法插入 id 值為 16、17、18、19 的這一些新記錄 。
  • 在特殊記錄( supremum pseudo-record)的主鍵索引上,加了范圍為 (20, +∞] 的 next-key 鎖,意味著其他事務無法插入 id 值大于 20 的這一些新記錄 。
我們也可以通過 select * from performance_schema.data_locks\G; 這條語句來看看事務 A 加了什么鎖 。
輸出結果如下,我這里只截取了行級鎖的內容 。
MySQL 是怎么加行級鎖的?為什么一會是 next-key 鎖,一會是間隙鎖,一會又是記錄鎖?

文章插圖
從上圖中的分析中,也可以得到事務 A 在主鍵索引上加了兩個 X 型 的next-key 鎖:
  • 在 id = 20 這條記錄的主鍵索引上,加了范圍為 (15, 20] 的 next-key 鎖,意味著其他事務即無法更新或者刪除 id = 20 的記錄,同時無法插入 id 值為 16、17、18、19 的這一些新記錄 。
  • 在特殊記錄( supremum pseudo-record)的主鍵索引上,加了范圍為 (20, +∞] 的 next-key 鎖,意味著其他事務無法插入 id 值大于 20 的這一些新記錄 。
實驗二:針對「大于等于」的范圍查詢的情況 。
假設事務 A 執行了這條范圍查詢語句:
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from user where id >= 15 for update;+----+-----------+-----+| id | name      | age |+----+-----------+-----+| 15 | 烏索普    |  20 || 20 | 香克斯    |  39 |+----+-----------+-----+2 rows in set (0.00 sec)事務 A 加鎖變化過程如下:
  1. 最開始要找的第一行是 id = 15,由于查詢該記錄是一個等值查詢(等于 15) , 所以該主鍵索引的 next-key 鎖會退化成記錄鎖 , 也就是僅鎖住 id = 15 這一行記錄 。
  2. 由于是范圍查找,就會繼續往后找存在的記錄 , 掃描到的第二行是 id = 20 , 于是對該主鍵索引加的是范圍為 (15, 20] 的 next-key 鎖;
  3. 接著掃描到第三行的時候,掃描到了特殊記錄( supremum pseudo-record),于是對該主鍵索引加的是范圍為 (20, +∞] 的 next-key 鎖 。
  4. 停止掃描 。
可以得知,事務 A 在主鍵索引上加了三個 X 型 的鎖 , 分別是:
MySQL 是怎么加行級鎖的?為什么一會是 next-key 鎖,一會是間隙鎖,一會又是記錄鎖?

文章插圖
  • 在 id = 15 這條記錄的主鍵索引上,加了記錄鎖 , 范圍是 id = 15 這一行記錄;意味著其他事務無法更新或者刪除 id = 15 的這一條記錄;
  • 在 id = 20 這條記錄的主鍵索引上,加了 next-key 鎖 , 范圍是 (15, 20]。意味著其他事務即無法更新或者刪除 id = 20 的記錄,同時無法插入 id 值為 16、17、18、19 的這一些新記錄 。
  • 在特殊記錄( supremum pseudo-record)的主鍵索引上,加了 next-key 鎖,范圍是 (20, +∞]。意味著其他事務無法插入 id 值大于 20 的這一些新記錄 。
我們也可以通過 select * from performance_schema.data_locks\G; 這條語句來看看事務 A 加了什么鎖 。
輸出結果如下,我這里只截取了行級鎖的內容 。
MySQL 是怎么加行級鎖的?為什么一會是 next-key 鎖,一會是間隙鎖,一會又是記錄鎖?

文章插圖
通過前面這個實驗,我們證明了: