news 2025/12/25 12:34:45

MySQL 各种锁机制详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL 各种锁机制详解

MySQL 各种锁机制详解

重点放在 InnoDB,引擎不同锁语义也不同。
目标:弄清楚“有哪些锁、锁什么粒度、什么时候会被加上”。


一、为什么需要锁?

数据库是“多人同时操作同一份数据”的系统:

  • 多个事务并发更新同一行;
  • 一个事务在扫一段范围时,另一个插入新数据;
  • 结构变更(DDL)和读写(DML)并发执行;

如果不加锁:

  • 数据会被“乱改”;
  • 读到一半被改、更新丢失、约束被破坏。

所以需要各种锁:

  • 控制并发写
  • 配合MVCC控制并发读写
  • 控制元数据变更(DDL)

MySQL 的锁大致可以从几类角度划分:

  1. 对象粒度:全局锁、库锁、表锁、行锁;
  2. 功能/用途:读锁(S)、写锁(X)、意向锁、元数据锁、间隙锁;
  3. 引擎:Server 层锁、InnoDB 锁、MyISAM 锁等。

下面重点围绕 InnoDB 来讲。


二、从大到小看:锁的粒度分类

2.1 全局锁(Global Lock)

  • 作用范围:整个实例(所有数据库、所有表)。
  • 常见命令:
FLUSHTABLESWITHREADLOCK;

作用:

  • 把整个实例“锁成只读”,常用于全库逻辑备份
  • 期间所有 DML、DDL 都会被阻塞(写不了)。

不常用,慎用,线上大量业务时基本不会直接这么干。


2.2 表级锁(Table Lock)

2.2.1 MySQL Server 层的显式表锁

语法:

LOCKTABLESt1READ,t2WRITE;UNLOCKTABLES;

特点:

  • 不区分引擎,属于 Server 层机制;
  • READ:其他会话可读不能写;
  • WRITE:其他会话不能读也不能写;
  • 粒度粗,并发度差,实际业务很少手工用。
2.2.2 MyISAM 的表锁

MyISAM 没有行锁,只有表锁:

  • 读锁(READ LOCK):多读互不阻塞;
  • 写锁(WRITE LOCK):写独占,阻塞其它读写。

这也是 MyISAM 不适合高并发写场景的重要原因。


2.3 元数据锁(Metadata Lock,MDL)

  • 作用对象:表结构(元数据)层面;
  • 自动加,不能手动控制。

场景:

  • 对一张表执行SELECT/INSERT/UPDATE/DELETE时:
    • 获得一个MDL 读锁
    • 阻止别人对该表执行结构变更(DDL);
  • 对表执行ALTER TABLE/DROP TABLE等 DDL 时:
    • 需要获取MDL 写锁
    • 会等待所有 MDL 读锁释放。

作用:

  • 保证 DDL 和 DML 不会“打架”;
  • 比如:你在跑查询时,不会有人把表给删了。

注意:

  • 长事务会长期持有 MDL 读锁;
  • 这会导致后续的 DDL 一直阻塞在“Waiting for table metadata lock”;
  • 线上经常见到这种场景。

2.4 行级锁(Row Lock)——InnoDB 主角

InnoDB 提供的行级锁包括:

  1. 记录锁(Record Lock)
  2. 间隙锁(Gap Lock)
  3. Next-Key Lock(记录锁 + 间隙锁)
  4. 插入意向锁(Insert Intention Lock)

以及上层逻辑上的:

  • 共享锁(S 锁,读锁)
  • 排他锁(X 锁,写锁)
  • 意向锁(意向共享 / 意向排他)

行级锁的特点:

  • 粒度细,并发度高;
  • 成本高于表锁;
  • 默认是行锁 + MVCC组合模式。

下面逐个拆。


三、InnoDB 行锁的类型

3.1 共享锁(S)和排他锁(X)

逻辑层面最常见的两种:

  • 共享锁(Shared Lock, S 锁)
    • 多个事务可以同时持有 S 锁;
    • 通常用于读,互相不冲突;
  • 排他锁(Exclusive Lock, X 锁)
    • 只允许一个事务持有;
    • 通常用于写,和其它 S/X 锁都不兼容(除自己)。

兼容矩阵(简化):

当前持有 \ 请求S 请求X 请求
S兼容冲突
X冲突冲突

常见 SQL:

-- 共享锁SELECT*FROMtWHEREid=1LOCKINSHAREMODE;-- 8.0 之后不推荐,用 FOR SHARESELECT*FROMtWHEREid=1FORSHARE;-- 排他锁SELECT*FROMtWHEREid=1FORUPDATE;

3.2 意向锁(Intention Lock)

作用对象:表级别,但用来配合行锁使用。

  • 意向共享锁(IS):事务打算在某些行上加共享锁;
  • 意向排他锁(IX):事务打算在某些行上加排他锁。

为什么需要意向锁?

  • 主要是为了配合表锁:
    • 如果要给整张表加表级 S/X 锁,需要知道表中是否存在行锁冲突;
    • 不可能一行行扫描,所以设计了“意向锁”。

行为:

  • 当事务要在某一行上加 X 锁时,会先在表上加 IX 锁;
  • 当事务要在某一行上加 S 锁时,会先在表上加 IS 锁。

表级锁与意向锁的兼容大致如下(记个直观印象即可):

ISIXS 表锁X 表锁
IS×
IX××
S 表锁××
X 表锁××××

总结:

  • 意向锁本身不会阻塞普通行锁;
  • 它的主要任务是:加速“表锁与行锁之间的冲突判断”

3.3 记录锁(Record Lock)

  • 锁定“索引上的某一条记录”;
  • 本质是:锁定某个索引键值。

例子:

SELECT*FROMuserWHEREid=10FORUPDATE;

假设id有索引:

  • 就会对id = 10这一条索引记录加记录锁(X 锁)
  • 其他事务不能修改或删除这条记录。

注意:
InnoDB 的行锁是基于索引实现的,没有索引就可能退化成表锁或锁一大片。


3.4 间隙锁(Gap Lock)

  • 锁定“索引之间的间隙”,不包括记录本身。

比如:索引里现有值:10, 20, 30, 40
则间隙为:(-∞,10)、(10,20)、(20,30)、(30,40)、(40,+∞)

间隙锁用来:

  • 阻止其他事务在某些范围“插入新记录”;
  • 本质目的是防止“幻读(Phantom Read)”

例子:

SELECT*FROMtWHEREageBETWEEN20AND30FORUPDATE;

InnoDB(在某些隔离级别)可能会:

  • 不仅锁定现有的满足条件的记录;
  • 还会锁定 20~30 之间的“间隙”,阻止插入新的 age 在这个范围内的数据;
  • 从而在后续同一事务再次查询时,不会出现“多出一条新的行”的幻读。

3.5 Next-Key Lock(记录锁 + 间隙锁)

  • 是“记录锁 + 间隙锁”的组合;
  • 锁定一个“左开右闭”的区间:(前一个索引值, 当前索引值]

在 InnoDB 默认的REPEATABLE READ下:

  • 对索引范围查询(带 for update / for share)会采用 Next-Key Lock;
  • 它既锁定记录本身,也锁定附近的间隙;
  • 减少幻读发生的可能。

简单理解:

Next-Key Lock = 将记录锁扩展到一个范围,以防止新记录插进来造成幻读。

3.6 插入意向锁(Insert Intention Lock)

一种特殊的间隙锁,用于插入时:

  • 当事务要在某个间隙插入记录时,会先声明一个“插入意向锁”;
  • 多个事务在不同位置插入,彼此不会互相阻塞;
  • 只有插入位置冲突时,才会等待。

四、InnoDB 锁是如何被加上的?

4.1 普通 SELECT(不加锁)

SELECT*FROMtWHEREid=10;
  • 默认是一致性读(Consistent Read)
  • 利用 MVCC 读取数据版本;
  • 一般不加行锁(除非特殊情况如手工 hint 或特定隔离级别)。

4.2 锁定读:SELECT … FOR UPDATE / FOR SHARE

-- 排他锁SELECT*FROMtWHEREid=10FORUPDATE;-- 共享锁SELECT*FROMtWHEREid=10FORSHARE;

特点:

  • 在可重复读 / 读已提交下,都会对符合条件的记录加行锁(记录锁/Next-Key Lock);
  • 会参与锁冲突判定;
  • 用于做“先查后改”的场景防止并发脏写。

4.3 UPDATE / DELETE 自动加锁

UPDATEtSETbalance=balance-100WHEREid=1;DELETEFROMtWHEREid=2;
  • InnoDB 自动对匹配的记录加排他锁(行锁)
  • 其他事务不能修改这些行,直到事务提交/回滚。

五、锁与索引的关系

一个非常重要的点:行锁是基于索引的。

  • 如果 WHERE 条件能用到索引:只锁命中的那几行;
  • 如果没用上索引:可能退化为锁住更多记录甚至全表

例子:

-- id 上有索引SELECT*FROMuserWHEREid=10FORUPDATE;-- ✅ 只锁 id = 10 对应的那条索引记录-- name 上无索引SELECT*FROMuserWHEREname='Tom'FORUPDATE;-- ❌ 可能会锁更大范围(扫描整个表,行锁挨个加,甚至接近表锁效果)

优化建议:

  • 对经常锁定某个字段的场景,要确保该字段有索引;
  • 避免在没有合适索引的条件上使用 FOR UPDATE / FOR SHARE。

六、MySQL 锁相关的典型问题

6.1 死锁(Deadlock)

典型死锁场景:

事务 A:锁记录 1 -> 再锁记录 2 事务 B:锁记录 2 -> 再锁记录 1

两边互相等对方释放锁,形成死锁。

InnoDB 会:

  • 自动检测死锁;
  • 回滚其中一个事务,报错:Deadlock found when trying to get lock

避免方案:

  • 访问多行时,尽量按照固定顺序加锁;
  • 控制事务粒度和时间,避免大事务;
  • 理解你的索引和锁范围。

6.2 锁等待

  • 如果锁冲突但不是死锁,就会出现等待;
  • 超过innodb_lock_wait_timeout(默认 50s)后报错。

排查手段:

SHOWENGINEINNODBSTATUS\G;

或在新版本里用performance_schema里的锁视图。


七、锁与隔离级别的关系(简要)

在不同隔离级别下:

  • 读未提交:大量读直接读最新版本,几乎不加锁,但允许脏读;
  • 读已提交:读时只看到已提交事务的最新版本,通常不加间隙锁;
  • 可重复读(默认)
    • 使用MVCC保证同一事务内多次读取一致;
    • 加上Next-Key Lock / 间隙锁避免/减少幻读;
  • 串行化:很多读都会退化为锁定读,强制串行执行,锁竞争最激烈。

简化理解:

隔离级别越高,加的锁越多或锁得越久,并发性能越差,但数据越“安全”。


八、常见锁类型速查表

锁类型粒度作用对象主要用途
全局锁实例所有库表全库备份,阻止写入
表锁整张表简单并发控制(MyISAM、多数不用)
元数据锁 MDL表结构 / 元数据DDL 与 DML 并发安全
行锁(记录锁)单条记录(索引项)控制并发更新单行
间隙锁索引间隙防止插入,避免幻读
Next-Key Lock记录 + 间隙InnoDB 默认可重复读的主要锁
插入意向锁插入位置多事务在不同位置插入时协调
S 锁行/表共享读允许多读,不允许写
X 锁行/表排他写写时独占,阻塞其它读写
意向锁 IS/IX声明将要在行上加 S/X 锁加速表锁与行锁冲突检测

九、小结

  1. MySQL 锁分层很多:全局锁、表锁、MDL、行锁等等。
  2. InnoDB 的并发控制核心是:行锁 + 间隙锁 + Next-Key Lock + MVCC
  3. 行锁基于索引实现,没索引容易锁更多数据甚至锁全表。
  4. 锁的细粒度在带来高并发能力的同时,也带来了死锁、锁等待等问题,需要通过:
    • 合理设计索引;
    • 控制事务范围和顺序;
    • 使用EXPLAINSHOW ENGINE INNODB STATUS等工具来排查。

真正摸清楚锁的行为,一般要结合:隔离级别 + 索引结构 + 实际 SQL反复实验和看执行计划。
这篇可以当成“概念地图”,后面你如果有具体 SQL,我可以帮你一起分析“加了哪些锁、锁到了哪一段”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/12 16:49:54

机器学习中所有可以调整的超参数(考试/自己调参用)

在机器学习/深度学习考试中,当被问到"你可以调整哪些超参数"时,以下是完整的超参数列表: 一、优化相关超参数 1. 学习率 (Learning Rate) 基础学习率:最重要的超参数学习率调度策略: 固定学习率衰减策略&…

作者头像 李华
网站建设 2025/12/12 16:49:19

《数字化破局抖音电商:从爆品打造到闭环运营实战》 第二章 第一节

前言 第一部分 盈利思维与运营基础 第1章 抖音电商盈利思维 1.1 盈亏平衡点分析:C一年半实战复盘 1.2 抖音电商的四种盈利模式及适用场景 1.3 IT思维做运营:数据驱动、系统思考、敏捷迭代 1.4 构建运营的“安全区”与“加速器”:与平台共生 第2章 抖音电商全景认知 …

作者头像 李华
网站建设 2025/12/12 16:49:18

终极指南:如何用MixedRealityToolkit快速构建混合现实应用

终极指南:如何用MixedRealityToolkit快速构建混合现实应用 【免费下载链接】MixedRealityToolkit The MixedRealityToolkit is a collection of scripts and components intended to accelerate the development of mixed reality applications targeting Windows M…

作者头像 李华
网站建设 2025/12/16 11:53:16

华为VRP基础及操作

目录 进入和退出系统视图 状态显示信息 配置文件管理 配置静态路由 华为静态路由实验 R1配置 R2配置 配置R1静态路由 配置R2静态路由 查看路由表 查看当前配置 配置电脑IP 测试PC1pingPC2 进入和退出系统视图 从用户视图进入系统视图:system-view 从系…

作者头像 李华
网站建设 2025/12/12 16:46:38

嵌入式代码优化实战:性能与功耗双赢

嵌入式代码优化实战技术文章大纲嵌入式代码优化概述嵌入式系统特点与优化需求优化目标:性能、功耗、内存占用常见优化误区与基本原则代码结构优化减少函数调用层级与内联函数使用循环展开与循环优化策略避免冗余计算与数据依赖内存优化技术静态内存分配与动态内存管…

作者头像 李华
网站建设 2025/12/23 14:43:50

VFXToolbox:视觉特效制作的全流程效率革命

VFXToolbox:视觉特效制作的全流程效率革命 【免费下载链接】VFXToolbox Additional tools for Visual Effect Artists 项目地址: https://gitcode.com/gh_mirrors/vf/VFXToolbox 还在为特效制作中的重复性工作头疼吗?VFXToolbox将彻底改变你的工作…

作者头像 李华