成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

記錄鎖、間隙鎖與 Next-Key Lock

數據庫 MySQL
現在 Gap Lock 間隙鎖,就是要把這些記錄之間的間隙也給鎖住,間隙鎖住了,就不用擔心幻讀問題了,這也是 Gap Lock 存在的意義。

有小伙伴在微信上表示面試時被問到了 Next-Key Lock 是啥,結果一臉懵逼,那么今天我們來捋一捋 MySQL 中的記錄鎖、間隙鎖以及 Next-Key Lock。

1. Record LockRecord

Lock 也就是我們所說的記錄鎖,記錄鎖是對索引記錄的鎖,注意,它是針對索引記錄,即它只鎖定記錄這一行數據。

例如如下一條 SQL:

select * from user where id=1 for update;

注意,id 是索引,id 如果不是索引,上面這條 SQL 所加的排他鎖就不是一個 Record Lock。

我們來看如下一個例子:

首先我們將系統變量 innodb_status_output_locks 設置為 ON,如下:

接下來我們執行如下 SQL,鎖定一行數據,此時會自動為表加上 IX 鎖:

接下來我們在一個新的會話中執行如下指令來查看 InnoDB 存儲引擎的情況:

show engine innodb status\G

輸出的信息很多,我們重點關注 TRANSACTIONS,如下:

可以看到:

  • TABLE LOCK table test08.user trx id 3564804 lock mode IX:這句就是說事務 id 為 3564804 的事務,為 user 表添加了意向排他鎖(IX)。
  • RECORD LOCKS space id 851 page no 3 n bits 80 index PRIMARY of table test08.user trx id 3564804 lock_mode X locks rec but not gap:這個就是一個鎖結構的記錄,這里的索引是 PRIMARY,加的鎖也是正兒八經的記錄鎖(not gap)。

看到了 LOCKS REC BUT NOT GAP,就說明這是一個記錄鎖。

那么這個 Record Lock 和我們之前所講的 S 鎖以及 X 鎖有什么區別呢?S 鎖是共享鎖,X 鎖是排他鎖,當我們加 S 鎖或者 X 鎖的時候,如果用到了索引,鎖加在了某一條具體的記錄上,那么這個鎖也是一個記錄鎖(其實,記錄鎖,S 鎖,X 鎖,概念有一些重復的地方,但是描述的重點不一樣)。

或者也可以理解為記錄鎖又細分為 S 鎖和 X 鎖,它們之間的兼容性如下圖:

兼容性

S 型記錄鎖

X 型記錄鎖

S 型記錄鎖

兼容

不兼容

X 型記錄鎖

不兼容

不兼容

2. Gap Lock

Gap Lock 也叫做間隙鎖,它的存在可以解決幻讀問題,另外需要注意,Gap Lock 也只在 REPEATABLE READ 隔離級別下有效。先來看看什么是幻讀,我們來看如下一個表格:

有兩個會話,A 和 B,先在會話 A 中開啟事務,然后查詢 age 為 99 的用戶總數,注意使用當前讀,因為在默認的隔離級別下,默認的快照讀并不能讀到其他事務提交的數據,至于快照讀和當前讀的區別,大家參考:S 鎖與 X 鎖,當前讀與快照讀!。當會話 A 中第一次查詢過后,會話 B 中向數據庫添加了一行記錄,等到會話 A 中第二次查詢的時候,就查到了和第一次查詢不一樣的結果,這就是幻讀(注意幻讀專指數據插入引起的不一致)。

在 MySQL 默認的隔離級別 REPEATABLE READ 下,上圖所描述的情況無法復現。無法復現的原因在于,在 MySQL 的 REPEATABLE READ 隔離級別中,它已經幫我們解決了幻讀問題,解決的方案就是 Gap Lock。

大家想想,之所以出現幻讀的問題,是因為記錄之間存在縫隙,用戶可以往這些縫隙中插入數據,這就導致了幻讀問題,如下圖:

如圖所示,id 之間有縫隙,有縫隙就有漏洞。前面我們所說的記錄鎖只能鎖住一條具體的記錄,但是對于記錄之間的空隙卻無能無力,這就導致了幻讀(其他事務可往縫隙中插入數據)。

現在 Gap Lock 間隙鎖,就是要把這些記錄之間的間隙也給鎖住,間隙鎖住了,就不用擔心幻讀問題了,這也是 Gap Lock 存在的意義。

給一條記錄加 Gap Lock,是鎖住了這條記錄前面的空隙,例如給 id 為 1 的記錄加 Gap Lock,鎖住的范圍是 (-∞,1),給 id 為 3 的記錄加 Gap Lock,鎖住的范圍是 (1,3),那么 id 為 10 后面的空隙怎么鎖定呢?MySQL 提供了一個 Supremum 表示當前頁面中的最大記錄,所以最后針對 Supremum 鎖住的范圍就是 (10,+∞),這樣,所有的間隙都被覆蓋到了,由于鎖定的是間隙,所以都是開區間。

那么我們怎么樣能看到 Gap Lock 呢?我給大家舉一個簡單的例子,假設我有如下一張表:

CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

一個簡單的表,id 是主鍵,age 是普通索引,表中有如下幾條記錄:

接下來我們執行如下 SQL,鎖定一行數據,此時也會產生間隙鎖:

接下來我們在一個新的會話中執行如下指令來查看 InnoDB 存儲引擎的情況:

show engine innodb status\G

輸出的信息很多,我們重點關注 TRANSACTIONS,如下:

紅色框選中的,就是一個間隙鎖的加鎖記錄,可以看到,在某一個記錄之前加了間隙鎖。

這就是間隙鎖。非常重要的一點需要大家牢記:Gap Lock 只在 REPEATABLE READ 隔離級別下有效。

3. Next-Key Lock

以下內容都是基于 MySQL 默認的隔離級別 REPEATABLE READ。

如果我們既想鎖定一行,又想鎖定行之間的記錄,那么就是 Next-Key Lock 了,換言之,Next-Key Lock 是 Record Lock 和 Gap Lock 的結合體。

正常來說,我們加行鎖的基本單位就是 Next-Key Lock,即既有記錄鎖又有間隙鎖,但是有時候 Next-Key Lock 會退化,我們通過幾個簡單的例子來分析一下。

首先我們來看看 Next-Key Lock 的加鎖規則:

  • 鎖的范圍是左開右閉。
  • 如果是唯一非空索引的等值查詢,Next-Key Lock 會退化成 Record Lock。
  • 普通索引上的等值查詢,向后遍歷時,最后一個不滿足等值條件的時候,Next-Key Lock 會退化成 Gap Lock。

我們通過幾個簡單的例子來分析下。

3.1 唯一非空索引

假設我有一個學生表,學生表中有學生的姓名和成績,如下:

CREATE TABLE `student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`score` double NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `score` (`score`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

id 是主鍵,score 是成績,其中 score 是唯一非空索引。

現在表中有如下數據:

假設我們執行如下 SQL:

在這個例子中,由于 score 是唯一非空索引,所以 Next-Key Lock 會退化成 Record Lock,換句話說,這行 SQL 只給 score 為 90 的記錄加鎖,不存在 Gap Lock,即我們新開一個會話,插入一條 score 為 88 的記錄也是 OK 的。

不過這里有一個特例,如果鎖定的是一個不存在的記錄,那么也會產生間隙鎖,例如下面這個:

由于并不存在 score 為 91 的記錄,所以這里會產生一個范圍為 (90,95) 的間隙鎖,我們執行如下 SQL 可以驗證:

可以看到,90.1、94.9 都會被阻塞(我按了 Ctrl C,所以大家看到查詢終止)。

90、95 則不符合唯一非空索引的條件。

95.1 則可以插入成功。

沒問題。

3.2 非空索引

現在我們重新開始,將 score 索引改為普通索引,如下:

CREATE TABLE `student` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`score` double NOT NULL,
PRIMARY KEY (`id`),
KEY `score` (`score`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

數據還是跟前面一樣,此時我們來執行如下 SQL:

我們來分析下。

此時要鎖定的是 id 為 90 的記錄,那么首先加間隙鎖,上一個 score 為 89,所以這次加的間隙鎖范圍是 (89,90),同時要鎖定 id 為 90 的記錄,所以進一步優化為 (89,90]。

同時,這里還有一條規則,就是滿足條件的上一條記錄,也需要被鎖住,所以最終的鎖范圍就是 [89,90]。

由于 score 不是唯一性索引,所以還需要繼續向后查找,找到的下一條記錄是 95,由于此時 Next-Key Lock 會退化成 Gap Lock,所以鎖定的范圍是 (90,95)。綜上,最終鎖定的范圍是 [89,95)。

接下來我們可以新開一個會話,我們分別嘗試添加如下數據看看是否能夠添加成功:

可以看到,score 為 88 是可以的,但是為 89.1 就不行。

score 為 95 也是可以的,但是為 94.9 就不行。

再試一下 89 是否可以:

說明我們上面分析的加鎖范圍是正確的。

再來看如下一條 SQL:

跟前面的案例相比,這次多了 limit 1,limit 1 表示只要一條記錄,所以這次查找到 90 之后就不會再往后查找了,那么最終的鎖就是間隙鎖+一個記錄鎖,最終的范圍就是 [89,90]。

此時新開一個會話,分別插入 score 為 88.9、89、90、91 的 記錄,驗證我們上面所分析的加鎖范圍:

88.9 和 89 的插入結果跟我們預想的一致。

可以看到,這里 90 也能插入,能插入的原因是因為缺乏 90 往后的間隙鎖。

4. 小結

MySQL 中的鎖有點繁雜,小伙伴們可以趁著某個周末,花點時間捋一捋,以后面試再遇到這些問題的時候就不頭大了。

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2025-04-24 10:56:01

MySQLInnoDB數據庫鎖

2024-06-12 14:03:31

MySQLInnoDB

2021-06-08 09:41:26

MySQL加鎖范圍

2021-06-05 18:02:20

MySQL加鎖范圍

2025-06-04 02:55:00

MySQL意向鎖記錄鎖

2023-06-05 08:15:30

MySQLInnoDB

2022-10-24 08:02:14

MySQL索引類型

2023-11-06 08:35:08

表鎖行鎖間隙鎖

2023-12-06 07:33:20

MySQL鎖事間隙鎖

2020-10-20 13:50:47

MySQL數據庫

2021-12-14 08:10:00

MySQL行鎖間隙鎖

2020-07-02 08:22:56

MySQL間隙鎖過行鎖

2024-01-16 12:19:08

MySQL重要機制高并發

2024-05-17 09:33:22

樂觀鎖CASversion

2011-11-28 12:55:37

JavaJVM

2013-12-19 13:25:40

InnoDB數據庫

2010-09-08 14:49:12

SQL Server數據庫

2024-03-11 00:00:00

mysqlInnoDB幻讀

2023-03-26 21:51:42

2022-03-18 10:44:46

S 鎖X 鎖快照
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产亚洲精品精品国产亚洲综合 | 亚洲欧洲在线视频 | 欧美中文字幕在线 | 日韩av一区在线观看 | 欧美一区二区三区精品 | 天堂色综合 | 精品99在线 | 四虎成人在线播放 | 国产大学生情侣呻吟视频 | 国产精品一区二区久久精品爱微奶 | 日韩精品在线观看免费 | 国产精品久久久久久久久久免费 | 91精品国产91久久久久游泳池 | 免费观看成人性生生活片 | 欧美三级电影在线播放 | 麻豆91av| 欧美在线一区二区三区四区 | 久久久久久91香蕉国产 | 亚洲在线看 | 日韩中文字幕视频在线 | 欧美激情在线精品一区二区三区 | 一级做a爰片久久毛片免费看 | 日韩一区二区黄色片 | 青青久久 | 一级片子 | 婷婷91| 国产97在线视频 | 久久久久久黄 | 亚洲精品一区二区三区四区高清 | 色眯眯视频在线观看 | 伊色综合久久之综合久久 | 久久99久久98精品免观看软件 | 亚洲欧美日韩电影 | 国产高清精品网站 | 久久久久久亚洲精品 | 欧美一区二区三区久久精品视 | 国产在线网址 | 精品在线观看一区二区 | 亚洲乱码国产乱码精品精的特点 | 成人h电影在线观看 | 色婷婷综合久久久中字幕精品久久 |