MySQL间隙锁与排他锁的区别全解析

 更新时间:2026年01月30日 09:26:56   作者:伐尘  
本文给大家介绍了MySQL间隙锁与排他锁的区别,文章提到了间隙锁在实际工作中的应用场景和注意事项,建议根据具体需求选择合适的锁机制,感兴趣的朋友跟随小编一起看看吧

【MySQL】间隙锁 与 排他锁 的区别

这是一个非常核心的数据库锁机制问题。简单来说:排他锁(X锁)是"锁什么",间隙锁(Gap Lock)是"锁哪里"

📊 核心区别对比表

特性排他锁 (X锁)间隙锁 (Gap Lock)
锁的类型锁类型 - 定义锁的"权限"锁范围 - 定义锁的"位置"
作用对象已存在的数据行数据行之间的间隙
兼容性与任何其他锁都不兼容与其他间隙锁兼容,但与插入意向锁冲突
主要目的防止其他事务读写数据防止其他事务在范围内插入新数据
可见范围行记录本身索引记录之间的"空隙"
何时使用UPDATE、DELETE、SELECT…FOR UPDATE可重复读隔离级别下的范围查询

🔍 详细解释

1. 排他锁(X锁)- 行级锁

-- 示例:对uid=8的行加排他锁
SELECT * FROM student WHERE uid = 8 FOR UPDATE;
-- 或
UPDATE student SET age = 60 WHERE uid = 8;

特点:

  • 锁定具体的数据行
  • 其他事务不能读取(SELECT…FOR UPDATE)也不能修改(UPDATE/DELETE)该行
  • 可以看作"写锁"

2. 间隙锁(Gap Lock)- 范围锁

-- 示例:锁定uid在(5, 10)之间的所有间隙
SELECT * FROM student WHERE uid BETWEEN 6 AND 9 FOR UPDATE;
-- 或
SELECT * FROM student WHERE uid > 5 AND uid < 10 FOR UPDATE;

假设你的表数据:

uid: 1, 2, 3, 4, 5, 7, 8, 10, 11

间隙包括:(-∞,1), (1,2), (2,3), …, (5,7), (7,8), (8,10), (10,11), (11,+∞)

特点:

  • 锁定索引记录之间的空隙,而不是记录本身
  • 防止其他事务在范围内插入新数据
  • 只在可重复读(REPEATABLE-READ) 隔离级别下有效

🎯 实际工作场景

场景1:防止幻读(Phantom Read)

-- 事务一
BEGIN;
SELECT * FROM student WHERE age BETWEEN 20 AND 30 FOR UPDATE;
-- 锁定所有age在20-30之间的间隙
-- 事务二尝试插入age=25的新记录(会被阻塞)
INSERT INTO student (name, age, sex) VALUES ('new_student', 25, 'M');

场景2:组合使用 - 临键锁(Next-Key Lock)

MySQL 实际上经常使用 **临键锁 = 记录锁 + 间隙锁**
-- 锁定uid=8的行及其前后的间隙
SELECT * FROM student WHERE uid = 8 FOR UPDATE;
-- 实际锁定:(7, 8] 和 (8, 10)

⚠️ 重要注意事项

1. 间隙锁只作用于非唯一索引

-- 如果name有唯一索引,不会加间隙锁
SELECT * FROM student WHERE name = 'bbbb' FOR UPDATE;
-- 只对'bbbb'这一行加排他锁
-- 如果name没有索引或不是唯一索引,可能会锁全表间隙
SELECT * FROM student WHERE name LIKE 'b%' FOR UPDATE;

2. 查看锁信息

-- 查看当前的锁(MySQL 8.0+)
SELECT 
    engine_transaction_id as trx_id,
    lock_type,
    lock_mode,
    lock_data,
    index_name
FROM performance_schema.data_locks 
WHERE object_name = 'student';

3. 死锁风险

间隙锁容易导致死锁,特别是并发插入时:

-- 事务A
BEGIN;
SELECT * FROM student WHERE uid = 15 FOR UPDATE; -- 间隙锁(10, +∞)
-- 事务B  
BEGIN;
SELECT * FROM student WHERE uid = 16 FOR UPDATE; -- 间隙锁(10, +∞)
-- 事务A
INSERT INTO student (uid, name) VALUES (15, 'test'); -- 等待B
-- 事务B
INSERT INTO student (uid, name) VALUES (16, 'test'); -- 等待A → 死锁!

🔧 性能影响与优化

情况影响解决方案
全表间隙锁锁住所有间隙,并发极差使用唯一索引查询
范围查询锁住大范围间隙缩小查询范围
批量操作可能锁大量间隙分批次操作
高并发插入容易死锁降低隔离级别为RC

💡 最佳实践建议

明确使用场景:

需要防止幻读 → 使用间隙锁(RR隔离级别)

只需要防止数据修改 → 使用行级排他锁

索引设计:

-- 好的设计:使用唯一索引避免不必要的间隙锁
CREATE UNIQUE INDEX idx_uid ON student(uid);
-- 查询时使用唯一索引
SELECT * FROM student WHERE uid = 8 FOR UPDATE; -- 只锁一行

隔离级别选择:

-- 如果不需要防止幻读,使用读已提交
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 此时不会加间隙锁

避免长事务:

-- 尽快提交事务,减少锁持有时间
BEGIN;
-- 立即执行需要加锁的操作
SELECT ... FOR UPDATE;
UPDATE ...;
-- 尽快提交
COMMIT;

📝 总结要点

  1. 排他锁是"行锁" - 锁已存在的数据
  2. 间隙锁是"范围锁" - 锁不存在的间隙
  3. MySQL 默认使用 临键锁(行锁+间隙锁)
  4. 间隙锁主要在 RR隔离级别 防止幻读
  5. 设计好索引可以大大减少不必要的间隙锁

在你的学生表例子中,如果 uid 是唯一索引,SELECT ... WHERE uid=8 FOR UPDATE 只会加行锁。如果 name 不是唯一索引,相同的查询可能会加间隙锁。

到此这篇关于MySQL间隙锁与排他锁的区别全解析的文章就介绍到这了,更多相关mysql间隙锁与排他锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL 8.0.29 安装配置方法图文教程(windows zip版)

    MySQL 8.0.29 安装配置方法图文教程(windows zip版)

    这篇文章主要为大家详细介绍了windows zip版MySQL 8.0.29 安装配置方法图文教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 深入Mysql字符集设置[精华结合]

    深入Mysql字符集设置[精华结合]

    深入Mysql字符集设置,建议大家看本文之前先看风雪之隅的文章,需要的朋友可以参考下
    2012-07-07
  • MySQL5.6使用mysqldump数据备份的实现

    MySQL5.6使用mysqldump数据备份的实现

    本文主要介绍了MySQL5.6使用mysqldump数据备份的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • MySQL主键生成的四种方式及对比详解

    MySQL主键生成的四种方式及对比详解

    在数据库设计中,主键(Primary Key)的选择至关重要,它不仅是数据行的唯一标识,还直接影响查询效率、数据存储甚至系统架构的扩展性,本文给大家分析了常见四种主键ID生成的方式,需要的朋友可以参考下
    2025-03-03
  • MySQL 添加索引5种方式示例详解(实用sql代码)

    MySQL 添加索引5种方式示例详解(实用sql代码)

    在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),感兴趣的朋友一起看看吧
    2025-05-05
  • 删除MySQL中所有表的外键的两种方法

    删除MySQL中所有表的外键的两种方法

    这篇文章主要介绍了删除MySQL中所有表的外键的两种方法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-05-05
  • 详解MySQL中default的使用

    详解MySQL中default的使用

    这篇文章主要介绍了MySQL中default的使用,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 设置和修改MySQL的root密码的详细教程

    设置和修改MySQL的root密码的详细教程

    在 MySQL 数据库的使用过程中,设置和修改 root 用户的密码是一项基本且重要的操作,root 用户拥有数据库的最高权限,因此确保其密码的安全性至关重要,本文将详细介绍在不同操作系统环境下设置和修改 MySQL root 密码的具体步骤,帮助你轻松掌握这一关键技能
    2025-05-05
  • linux下mysql 5.1 和 5.7的安装教程

    linux下mysql 5.1 和 5.7的安装教程

    下面小编就为大家分享一篇linux下mysql 5.1 和 5.7的安装教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • MySQL需要根据特定顺序排序的实现方法

    MySQL需要根据特定顺序排序的实现方法

    在MySQL中,我们可以通过指定顺序排序来在查询结果中控制数据的排列顺序,这种排序方式是非常有用的,本文就来介绍一下,感兴趣的可以了解一下
    2023-11-11

最新评论