当前位置: 代码网 > it编程>数据库>Mysql > MySQL InnoDB锁机制之从Record到Next-Key的使用解读

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

2025年12月26日 Mysql 我要评论
在真实业务中,你遇到的大多数 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 锁。

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

  • MySQL中的表操作及查询方式

    MySQL中的表操作及查询方式

    一.表操作mysql的操作中,一些专用的词无论是大写还是小写都是可以通过的。1.插入数据insert [into] table_name (列名称…)value... [阅读全文]
  • MySQL 存储引擎层常见问题详解

    MySQL 存储引擎层常见问题详解

    一、mysql 存储引擎层是什么?mysql 的存储引擎层(storage engine layer)是数据库系统中负责数据实际存储和检索的核心模块。它将 sq... [阅读全文]
  • MySQL死锁排查指南

    MySQL死锁排查指南

    mysql死锁排查指南作为一名10年经验的java工程师,我会从场景、排查、解决三个维度,带你搞定mysql死锁问题。一、先搞懂:死锁是什么?死锁是多个事务互相... [阅读全文]
  • MySQL表数据删除与清理的最佳实践

    在mysql运维中,“删除”操作看似简单,却隐藏着诸多风险——误删表导致数据永久丢失、delete全表引发主从延迟、删数据后磁盘空间…

    2025年12月25日 数据库
  • MySQL分页查询优化的实践指南

    引言在日常业务开发中,分页查询是高频操作,比如列表页数据展示、历史记录查询等。但当数据量达到万级以上时,普通的limit分页往往会出现性能瓶颈。本文基于实际测试场景,详细分析mys…

    2025年12月25日 数据库
  • MySql基础知识总结SQL优化技巧

    本篇是mysql知识体系总结系列的第二篇,该篇的主要内容是通过explain逐步分析sql,并通过修改sql语句与建立索引的方式对sql语句进行调优,也可以通过查看日志的方式,了解…

    2025年12月24日 数据库

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com