当前位置: 首页 > news >正文

深入理解MySQL行锁,间隙锁和临键锁

1.行锁 (Record Lock)

锁住索引中的一条具体记录。 保证原子性:防止多个事务同时修改同一条记录
例如:SELECT * FROM t WHERE id = 10 FOR UPDATE;会在 id=10这条记录的索引上加行锁。

示例

-- 事务A
BEGIN;
SELECT * FROM users WHERE id = 10 FOR UPDATE;-- 此时其他事务执行以下操作会被阻塞:
-- UPDATE users SET name = 'new' WHERE id = 10;
-- DELETE FROM users WHERE id = 10;

2.间隙锁(Gap Lock)

锁住索引记录之间的间隙,但不包括记录本身。唯一目的就是防止其他事务在这个间隙中插入新记录,解决幻读问题。
它是一个开区间。例如:假设表中有 id为 5, 10, 15 的记录。那么间隙锁可以锁住 (-∞, 5),(5, 10),(10, 15),(15, +∞)这些范围。

触发时机

(1)在可重复读或串行化隔离级别下。
(2)唯一索引/普通索引,等值查询,记录不存在时。

示例

表 user,其 age字段上有普通索引
在这里插入图片描述

事务A:
BEGIN;
SELECT * FROM user WHERE age = 25 FOR UPDATE; 由于 age=25不存在,InnoDB 会找到 25所在的间隙,即 (20, 30)。此时,事务 A 会在 (20, 30)这个间隙上加间隙锁。事务B:
INSERT INTO user (id, age) VALUES (10, 22); -- 阻塞。因为 22 在 (20, 30) 区间内
INSERT INTO user (id, age) VALUES (10, 28); -- 阻塞。因为 28 在 (20, 30) 区间内
INSERT INTO user (id, age) VALUES (10, 20); -- 成功。20 是已存在的记录,不在间隙锁范围内(但可能被记录锁或临键锁影响)
INSERT INTO user (id, age) VALUES (10, 30); -- 成功。30 是已存在的记录,不在间隙锁范围内事务 B 的插入操作会被阻塞,直到事务 A 提交。这样就防止了在事务 A 中如果再次执行 SELECT ... FOR UPDATE可能会看到新插入的 age=2228的记录(幻读)。

3.临键锁(Next-Key Lock)

行锁 + 间隙锁。它锁住一条记录和该记录之前的间隙。它是一个左开右闭区间。临键锁是 InnoDB 默认的行锁模式
例如:对于记录 id=10,它的临键锁会锁住 (5, 10]这个区间。这意味着既不能插入 id=6的新记录(间隙被锁),也不能修改或删除 id=10的记录(记录被锁)。

示例

(1)等值查询

事务A
SELECT * FROM users WHERE age = 20 FOR UPDATE;

过程:InnoDB 通过 B+ 树找到 age=20 的记录,并给它加上临键锁。

锁定的范围:(10, 20]。

为什么不是 [20, 20]?因为临键锁的本质是锁“下一个键”之前的间隙。对于 age=20,它会锁住 (上一个记录的值, 20],即 (10, 20]。

(2)范围查询

事务A
SELECT * FROM users WHERE age BETWEEN 15 AND 25 FOR UPDATE;

找到第一条满足条件的记录,即 age=20。锁住 (10, 20]。

继续向后扫描,找到 age=30。虽然 30 不满足条件(30 > 25),但根据规则,扫描到的记录也要加锁。锁住 (20, 30]。

最终锁定的范围:(10, 20] 和 (20, 30]。这相当于锁定了整个 (10, 30] 的区间。

效果:任何试图在 age=15 到 age=30 之间插入、更新记录的操作都会被阻塞。

(3)特殊场景:唯一索引等值查询

当使用唯一索引进行等值查询并且数据存在时,InnoDB 会优化,降级为仅使用行锁。

SELECT * FROM users WHERE id = 3 FOR UPDATE;
此时,InnoDB 知道 id=3 是唯一的,不需要防止幻读,所以只会锁住 id=3 这一条记录本身,而不会加间隙锁。

相关SQL语句

-- 查看当前锁信息
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;-- MySQL 8.0+ 性能schema锁监控
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;
http://www.dtcms.com/a/581218.html

相关文章:

  • 鸿安建设集团网站wordpress主题2019
  • 申请软著,怎么快速整理软件源代码
  • sam2 点选 分割图片 2025
  • 网站开发源程序重庆建筑人才网官网
  • 如何理解蒙特卡洛方法并用python进行模拟
  • 公司网站代码模板wordpress 虎嗅网
  • 在 Windows 中清理依赖node_modules并重新安装
  • 【数据结构】从零开始认识图论 --- 并查集与最小生成树算法
  • 使用 AWS WAF 防护 Stored XSS 攻击完整指南
  • 当爬虫遇到GraphQL:如何分析与查询这种新型API?
  • 游戏手柄遥控越疆协作机器人[一]
  • MATLAB实现决策树数值预测
  • Maven 多模块项目与 Spring Boot 结合指南
  • 搜索量最高的网站小白学编程应该从哪里开始学
  • 西安大型网站制作wordpress耗时显示
  • Kubernetes(k8s)
  • 如何提高 SaaS 产品的成功率?
  • ​技术融合新纪元:深度学习、大数据与云原生的跨界实践
  • 中国高分辨率单季稻种植分布数据集(2017-2023)
  • PDF工具箱/合并拆分pdf/提取图片
  • 如何在PDF文档中打钩?(福昕阅读器)打√
  • 新手怎么样学做网站企业网站建设规划的基本原则是什么
  • 【DIY】PCB练习记录2——51单片机核心板
  • Spring Boot 2.7.18(最终 2.x 系列版本)3 - 枚举规范定义:定义基础枚举接口;定义枚举工具类;示例枚举
  • aspnet东莞网站建设多少钱frontpage怎样做网站
  • uniapp 使用renderjs 封装 video-player 视频播放器, html5视频播放器-解决视频层级、覆盖、播放卡顿
  • 基于深度对比学习的分析化学结构注释TOP1匹配率提升研究
  • MFA MACOS 安装流程
  • Ubuntu 上部署 Microsoft SQL Server 详细教程
  • 网站上面怎么做链接微信网站合同