MySQL InnoDB锁机制之从Record到Next-Key的使用解读

 更新时间:2025年12月26日 09:42:13   作者:kkkkkkkkl24  
这篇文章详细介绍了InnoDB的锁机制,包括记录锁(RecordLock)、间隙锁(GapLock)和Next-KeyLock,以及它们的触发条件和作用,通过理解这些锁的机制,读者可以更好地解决MySQL中的性能问题、死锁问题和幻读问题

在真实业务中,你遇到的大多数 MySQL 性能问题、死锁问题,几乎都与“锁”有关。但很多工程师对锁的理解停留在碎片层面:

知道“行锁”“间隙锁”“next-key-lock”,但不知道 SQL 是如何触发这些锁的、锁到底锁在哪里、为什么会锁这么多

这一篇文章,我会用工程化思维,带你一次性理解 InnoDB 锁机制的全景图

看完以后,你将具备:

  • ✔ 能看懂锁的真实作用
  • ✔ 能从 SQL 推断出锁范围
  • ✔ 能解释死锁发生原因
  • ✔ 能在面试中条理清晰地讲出锁机制

一、为什么 InnoDB 的锁机制这么复杂?

MySQL 采用 MVCC + 锁 实现事务隔离,其中最关键的隔离级别是:

  • RC:读已提交
  • RR:可重复读(默认)

RR 是企业最常见的隔离级别,它要解决“幻读”问题。

于是有了三个锁:

  • 记录锁(Record Lock)
  • 间隙锁(Gap Lock)
  • Next-Key Lock(Record + Gap)

所有复杂问题都来自这个组合。

二、InnoDB 的三种核心锁(理解它们的作用和触发条件)

Record Lock:真实行上的锁

  • 锁的对象:一条真实存在的记录
  • 触发场景:精确命中唯一索引

例如:

SELECT * FROM user WHERE id = 10 FOR UPDATE;

只锁 (10] —— 单条记录。

特点:不会锁间隙,因此不会阻止插入。

Gap Lock:只锁“间隙”,不锁数据

作用:阻止“间隙内插入新数据”,防止幻读。

例如:

索引中已有值:

10 --- 20 --- 30

SQL:

SELECT * FROM user WHERE age > 20 FOR UPDATE;

Gap Lock 会锁住:

(20, 30)
(30, +∞)

重点:Gap Lock 不锁记录,只锁区间。

Next-Key Lock:Record + Gap 的组合锁

RR 下范围查询的默认锁模式:

(prev_key, record_key]

例如:(假设索引有 10、20、30)

SELECT * FROM t WHERE age BETWEEN 15 AND 25 FOR UPDATE;

锁住的区间:

(10,20]
(20,30]

作用:

  • ✔ 锁住命中的记录
  • ✔ 锁住记录前的 gap → 阻止插入

这就是为什么 RR 隔离级别能规避幻读。

三、锁到底由哪些 SQL 触发?

“ SQL → 锁类型” 映射表:

SQL 场景索引情况锁类型原因
WHERE id = ?(唯一键)精确命中Record Lock不需要锁 gap
WHERE id = ?(普通索引)精确匹配,但非唯一Next-Key Lock防止幻读
WHERE age > ? / < ?范围扫描Next-Key Lock必须锁 gap
BETWEEN 范围查询范围扫描Next-Key Lock防止插入
无索引过滤全表扫描大量 Record Lock每条记录都会被锁
LIKE '%abc'无法走索引表锁风险全表扫描

一句话总结:

  • 能精确锁住记录 → Record Lock
  • 需要范围扫描 → Next-Key Lock
  • 范围扫描一定会锁 gap → Gap Lock

四、锁具体加在什么区间?

假设索引中有如下值:

10 ---- 20 ---- 30 ---- 40

来看不同 SQL 加的锁👇

WHERE id = 20 FOR UPDATE

锁:

(10, 20]

但如果字段是主键/唯一键,会优化成:

[20]

WHERE id > 20 FOR UPDATE

锁:

(20,30)
(30,40)
(40,+∞)

WHERE id BETWEEN 15 AND 35 FOR UPDATE

锁:

(10,20]
(20,30]
(30,40]

无索引条件

SELECT * FROM user WHERE name='xxx' FOR UPDATE;

锁住所有记录:

[10], [20], [30], [40]

→ 大量锁冲突发生的根源。

五、总结

  • InnoDB 的锁永远基于索引。
  • 无法精确匹配记录,就会使用 Next-Key Lock。
  • 范围查询一定会带 gap 锁。

掌握这三点后,死锁、锁等待、幻读问题都能一眼看穿。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Windows10 64位安装MySQL5.6.35的图文教程

    Windows10 64位安装MySQL5.6.35的图文教程

    这篇文章主要介绍了Windows10 64位安装MySQL5.6.35的图文教程,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-02-02
  • MySQL分页技术、6种分页方法总结

    MySQL分页技术、6种分页方法总结

    这篇文章主要介绍了MySQL分页技术、6种分页方法总结,本文总结了6种分页的方法并分别一一讲解它们的特点,需要的朋友可以参考下
    2015-07-07
  • mysql installer web community 5.7.21.0.msi安装图文教程

    mysql installer web community 5.7.21.0.msi安装图文教程

    这篇文章主要为大家详细介绍了mysql installer web community 5.7.21.0.msi,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • mysql忘记密码的解决方法

    mysql忘记密码的解决方法

    mySQL忘記管理密碼的解決方法 ! 如果mySQL正在運作,請先關閉,
    2008-06-06
  • ubuntu20.04配置mysql8.0的实现步骤

    ubuntu20.04配置mysql8.0的实现步骤

    本文主要介绍了ubuntu20.04配置mysql8.0的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • MySql nion与Limit查询介绍

    MySql nion与Limit查询介绍

    这篇文章主要为大家详细介绍一下MySQL数据库中union、limit查询的使用,文中的示例代码讲解详细,对我们学习MySQL有一定帮助,需要的可以参考一下
    2022-09-09
  • Mysql 执行一条语句的整个过程详细

    Mysql 执行一条语句的整个过程详细

    这篇文章主要介绍了Mysql 执行一条语句的整个详细过程,Mysql的逻辑架构整体分为两部分,Server层和存储引擎层,下面文章内容具有一定的参考价值,需要的小伙伴可以参考一下,希望对你有所帮助
    2022-02-02
  • 重置mysql的root密码最简单的方法

    重置mysql的root密码最简单的方法

    在本篇文章里小编给大家整理的是关于重置mysql的root密码最简单的方法,需要的朋友们参考下。
    2020-03-03
  • MySql导入CSV文件或制表符分割的文件

    MySql导入CSV文件或制表符分割的文件

    这篇文章主要为大家详细介绍了MySql导入CSV文件或制表符分割的文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 深入理解MySQL中的事务机制

    深入理解MySQL中的事务机制

    这篇文章主要介绍了MySQL中的事务机制,事务机制在各大MySQL教程中均为重要知识,需要的朋友可以参考下
    2015-06-06

最新评论