精品一区二区三区在线成人,欧美精产国品一二三区,Ji大巴进入女人66h,亚洲春色在线视频

面試官:什么是 Next-Key Lock?作用是什么?

數據庫 其他數據庫
Next-Key Lock 是 InnoDB 引擎行鎖加間隙鎖的組合,它鎖住的是一個前開后閉的區間,消除了 REPEATABLE READ 隔離級別下的幻讀問題。

Next-Key Lock 是 InnoDB 存儲引擎中非常基礎也是非常重要的一個鎖。今天來聊一聊 Next-Key Lock。

首先我們回顧一下 MySQL 的事務隔離級別。

  • 串行化(Serializable):事務對數據讀寫都是串行的。
  • 可重復讀(Repeatable Read):事務執行過程中,多次讀取同一行數據,讀取結果一致。MySQL 默認隔離級別就是可重復讀。
  • 讀已提交數據(Read Committed):事務執行過程中,如果有其他事務修改了數據并且提交事務,當前事務可以讀取到最新提交的數據。
  • 讀未提交數據(Read Uncommitted):事務執行過程中,可以讀取到其他事務未提交的數據。

可重復讀隔離級別解決了幻讀問題,而解決的方式就是通過 MVCC 和 Next-Key Lock。

幻讀:同一事務內多次查詢同一范圍內的數據,因其他事務插入或刪除符合條件的數據,導致事務在后面讀取到的結果集不一樣,像產生了幻覺。

介紹

Next-Key Lock 是間隙鎖(gap lock)和行鎖(index-record lock)的組合。

  • 行鎖: 鎖定索引中的某一條具體記錄。
  • 間隙鎖: 鎖定索引記錄之間的間隙,它鎖定的是一個范圍,這個范圍內不存在數據。例如,如果鎖定了 (10, 20) 這個范圍,那其他事務就不能在這個范圍內插入新記錄。

一個 Next-Key Lock,也就是行鎖加上該行之前的間隙鎖,因此,它鎖定的是一個前開后閉區間。

我們假設有一張表 t,包含(id,a,b)3 個字段,其中 id 是主鍵,字段 a 上面有普通索引,字段 b 沒有索引。建表語句如下:

CREATE TABLE `t` ( 
`id` int(10) NOT NULL, 
`a` int(10) DEFAULT NULL, 
`b` int(10) DEFAULT NULL, 
PRIMARY KEY (`id`), 
KEY `idx_a` (`a`)) ENGINE=InnoDB;

表中有 4 條記錄,分別(5,5,5),(10,10,10),(15,15,15),(20,20,20),那如果執行下面語句:

select * from t where id = 7 for update;

這樣會對 id= 10 的記錄加 Next-Key Lock,鎖定的是 (5, 10] 這個區間,也就是說,除了鎖住 id = 10 這條記錄(行鎖),同時間隙鎖鎖住了 5 和 10 之間的間隙(5,10)。

而如果執行下面這條 SQL,則會對整張表加 Next-Key Lock,因為字段 c 沒有索引,新插入的數據都可能包含 c = 6。加鎖后,形成 5 個范圍:

select * from t where c = 6 for update;

圖片圖片

加上了 Next-Key Lock,可以阻止其他事務在被鎖定的間隙中插入新的記錄,從而保證了當前事務中多次執行相同查詢時,不會有新的記錄查出來,解決了幻讀問題。

在可重復隔離級別下,執行下面幾個 SQL 時,都可能會對掃描過程中訪問到的記錄加 Next-Key Lock:

SELECT * from t where id =xxx FOR UPDATE;//id 不存在
SELECT * from t where a =xxx FOR UPDATE;
SELECT * from t where b =xxx FOR UPDATE;
SELECT * from t where id BETWEEN 10 AND 20;
SELECT * from t where id =xxx LOCK IN SHAREMODE;
UPDATE t set b = xxx where id = yyy;
DELETE from t where id = yyy;

非唯一索引和無索引的字段,都可能會匹配多條記錄,所以會加 Next-Key Lock。

那如果查詢的 id 存在,還會加 Next-Key Lock 嗎? 比如上面的表,執行 SQL:

SELECT * from t where id = 10 for update;

答案是不會加 Next-Key Lock,這個時候 Next-Key Lock 退化成了行鎖。

查詢語句符合下面三個條件時,Next-Key Lock 會退化成行鎖:

  1. 查詢使用的是唯一索引;
  2. SQL 條件是等值匹配(比如 WHERE unique_key = X);
  3. 掃描到的記錄確定存在。

如果上面 3 個條件有一個不符合 ,都會加 Next-Key Lock。

另一點,雖然 Next-Key Lock 是前開后閉區間,如果索引上等值查詢向右遍歷到最后一個值不滿足等值條件,則退化為間隙鎖。比如執行下面 SQL:

SELECT * from t where id = 8 for update;

Next-Key Lock 退化為間隙鎖,加鎖范圍是(5,10)。id = 10 的這條記錄不影響其他事務修改操作。

優缺點

優點:解決了 REPEATABLE READ 隔離級別下幻讀問題,有效保證了數據一致性。

缺點: 增加了鎖的粒度,一定情況下會降低并發性能,并增加死鎖發生的概率。因為多個事務可能以不同的順序請求對重疊的間隙加鎖,很容易造成死鎖。

下面是一個死鎖的案例,事務 A 準備插入一條(8,8,8)的記錄,事務 B 準備插入一條(9,9,9)的記錄,其他他們相互不影響,但加了 Next-Key Lock,就容易造成死鎖。

事務 A

事務 B

select * from t where id = 8 for update;



select * from t where id = 9 for update;


insert into t values(9,9,9);

insert into t values(8,8,8);


這樣兩個事務都會加(5,10)這個間隙鎖,最終相互等待,形成死鎖。

為什么兩個事務都可以加上間隙鎖,因為間隙鎖之間不會沖突。

總結

Next-Key Lock 是 InnoDB 引擎行鎖加間隙鎖的組合,它鎖住的是一個前開后閉的區間,消除了 REPEATABLE READ 隔離級別下的幻讀問題。理解 Next-Key Lock 要把握兩點:

  1. 可重復隔離級別下才會生效;
  2. 鎖住一個前開后閉的區間,但一定條件下可能退化成行鎖或者間隙鎖。
責任編輯:武曉燕 來源: 君哥聊技術
相關推薦

2021-06-05 18:02:20

MySQL加鎖范圍

2021-07-06 07:27:45

React元素屬性

2021-03-01 12:40:02

JavaserialVersi代碼

2021-06-08 09:41:26

MySQL加鎖范圍

2022-02-18 11:06:12

首席技術官技術人工智能

2022-04-29 11:39:28

MySQL幻讀Gap Lock

2021-09-07 10:44:33

Java 注解開發

2025-03-05 00:01:00

ReduxReact

2025-04-24 10:56:01

MySQLInnoDB數據庫鎖

2025-03-05 02:10:00

2024-06-12 14:03:31

MySQLInnoDB

2023-12-06 09:10:28

JWT微服務

2025-09-01 09:05:00

2021-12-08 06:53:29

面試動態代理

2024-02-22 15:36:23

Java內存模型線程

2022-09-29 07:30:57

數據庫索引字段

2025-08-04 08:05:28

2025-07-15 02:15:00

MySQL索引回表

2009-07-07 16:38:36

ServletCont

2021-02-19 10:02:57

HTTPSJava安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 汕尾市| 房山区| 禄劝| 栖霞市| 石家庄市| 彭水| 南汇区| 平罗县| 长宁区| 贵港市| 伊金霍洛旗| 漳平市| 漳州市| 灵宝市| 桃源县| 巴塘县| 信宜市| 东乡族自治县| 澳门| 板桥市| 都安| 南昌市| 彭阳县| 达拉特旗| 巩义市| 潢川县| 龙州县| 封丘县| 育儿| 永吉县| 禹城市| 伊吾县| 根河市| 大同县| 兰坪| 安新县| 甘肃省| 鹿邑县| 准格尔旗| 望城县| 凤山县|