0

0

mysql执行SQL时会加哪些锁_mysql并发锁流程说明

P粉602998670

P粉602998670

发布时间:2026-02-27 11:28:03

|

293人浏览过

|

来源于php中文网

原创

select是否加锁取决于隔离级别和索引:rr下普通select为快照读不加锁,但select...for update必加锁;有索引时加行级锁,无索引可能锁全表。

mysql执行sql时会加哪些锁_mysql并发锁流程说明

SELECT 不加锁?得看隔离级别和有没有索引

MySQL 的锁行为不是由 SQL 类型绝对决定的,而是和事务隔离级别、语句是否走索引、执行计划强相关。比如 SELECT * FROM t WHERE id = 1 在 RR(可重复读)下,如果 id 是主键,InnoDB 会加 **行级记录锁(Record Lock)**;如果 id 没索引,就会退化为 **表级意向锁 + 间隙锁或临键锁的组合**,甚至全表扫描时锁住所有聚簇索引页。

常见误区是认为 “SELECT 不锁表”,其实只在 RC(读已提交)下搭配唯一索引查询才可能不加锁(快照读),但一旦用了 SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE,不管什么级别都立刻加锁。

  • RR 下普通 SELECT 是快照读,不加锁(但背后有 MVCC 版本链维护)
  • RC 下普通 SELECT 也是快照读,不过只保证语句级一致性,不保证事务内一致性
  • 任何 SELECT ... FOR UPDATE 都会触发当前读,并加记录锁或临键锁
  • 没走索引的 WHERE 条件,即使只是 SELECT ... FOR UPDATE,也可能锁全表(实际是锁所有扫描到的索引页)

UPDATE/DELETE 加的是临键锁(Next-Key Lock),不只是行锁

InnoDB 默认在 RR 隔离级别下对范围条件使用 **临键锁(Next-Key Lock)**,即“记录锁 + 间隙锁”的合体。它既锁住匹配的记录,也锁住该记录前的间隙,防止幻读。比如 UPDATE t SET name='x' WHERE age > 20,哪怕 age 有索引,也会锁住所有满足 age > 20 的记录及其右侧间隙。

这个设计常被低估:你以为只改几行,实际上可能锁住一大片索引范围,导致其他事务在相邻值上插入/更新被阻塞。

  • 唯一索引等值查询(如 WHERE id = 100)→ 只加记录锁(Record Lock)
  • 非唯一索引等值查询(如 WHERE name = 'a')→ 加临键锁(锁该值+前间隙)
  • 范围查询(>=BETWEENLIKE 'abc%')→ 加临键锁,覆盖整个扫描区间
  • DELETEUPDATE 的锁行为完全一致,都基于执行计划决定锁粒度

INSERT 会触发隐式锁和插入意向锁(Insert Intention Lock)

新插入一行时,InnoDB 并不会直接加记录锁,而是先判断插入位置是否被其他事务用临键锁封锁。如果没有冲突,就完成插入;如果有,就等待对方释放间隙上的锁。这时等待方持有的是 **插入意向锁(Insert Intention Lock)**——一种特殊的间隙锁,表示“我想在这个间隙插一条记录”。

Getsound
Getsound

基于当前天气条件生成个性化音景音乐

下载

关键点在于:插入意向锁之间互不冲突(多个事务可以同时申请同一间隙的插入意向锁),但会与临键锁/间隙锁冲突。这也是为什么两个事务同时 INSERT INTO t VALUES (5) 到同一个空缺位置时不会死锁,但如果一个事务持有 WHERE id > 3 AND id 的临键锁,另一个事务插 <code>id = 5 就会被阻塞。

  • 插入前会检查插入点所在间隙是否被其他事务的临键锁覆盖
  • 插入意向锁本身不阻塞其他插入意向锁,只阻塞临键锁/间隙锁
  • 自增主键插入会额外持有 auto-inc lock(表级锁),影响并发 INSERT 性能
  • 唯一键冲突时,INSERT 会先加记录锁去查冲突行,再决定报错 or 更新(ON DUPLICATE KEY)

如何快速确认某条 SQL 实际加了什么锁?

别猜,用 INFORMATION_SCHEMA.INNODB_TRX + INNODB_LOCKS(MySQL 5.6/5.7)或 performance_schema.data_locks(8.0+)直接查。最实用的是结合 SHOW ENGINE INNODB STATUS\G,看其中的 TRANSACTIONSLATEST DETECTED DEADLOCK 部分。

更轻量的方式是:开启事务,执行目标 SQL,然后立刻查:

SELECT * FROM performance_schema.data_locks\G

输出里重点关注 LOCK_TRX_IDLOCK_MODE(如 RECORDREC_GAPNEXT_KEY)、LOCK_DATA(具体锁住的索引值)。

  • MySQL 8.0 必须开启 performance_schema 且设置 innodb_monitor_enable = "all" 才能捕获完整锁信息
  • LOCK_MODE = X, REC_NOT_GAP 表示独占记录锁;X, GAP 是间隙锁;X, NEXT_KEY 是临键锁
  • 如果看到大量 WAITING 状态的锁,说明有阻塞,配合 data_lock_waits 查谁在等谁
  • 不要依赖 explain 判断锁类型——explain 只显示执行计划,不反映锁行为

实际并发场景中,锁的复杂性往往藏在“看似简单”的条件里:比如一个 ORDER BY created_at LIMIT 1 查询,如果 created_at 没索引,可能触发全表扫描+全表临键锁;又比如批量 UPDATE 用子查询,子查询结果集越大,锁住的索引范围越广。这些细节不查 data_locks 很难定位。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1047

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

339

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

379

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1884

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

378

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1437

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

585

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

437

2024.04.29

html5播放器怎么用
html5播放器怎么用

本合集全面介绍HTML5播放器的使用方法,涵盖基础语法、自定义控制、兼容性处理及实战示例。阅读专题下面的文章了解更多详细内容。

0

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.4万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 837人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号