mysql executeupdate 一条UPDATE语句在MySQL 8.0中到底加了几把锁?
mysql executeupdate 一条UPDATE语句在MySQL 8.0中到底加了几把锁?
理解MySQL的锁,可以先从它的架构设计入手。SQL语句进来后,要经过哪些节点:层的元数据锁、的意向锁(IS/IX)、行级锁,每层管的粒度不同。先看架构设计,再看每层有哪些锁,会更容易理解和记住。
一条语句,其实会同时涉及元数据共享写锁、意向排他锁IX、行级排他锁。
如果能从三层架构入手去理解,后面不管面试还是排查问题,心里都比较有数。
你可以通过下图,先大概看一下,从架构层面,一条语句是怎么执行的。

锁的分层设计
锁的设计和数据库的分层架构是一致的。

用餐厅来比喻:
SQL语句执行时,先经过层检查元数据锁,再进入(需要锁行时加意向锁),最后才到行级锁。排查锁问题时,也按这个顺序:先看元数据锁有没有长事务占着表定义,再看有没有意向锁,最后看行级锁。
每层架构里的锁
上一节的表格把三层锁介绍了一遍mysql executeupdate,下面按架构从上到下展开,先说每种锁管什么、典型场景是什么。
层:元数据锁MDL
元数据锁保护的是表结构,不是行数据。层在语句真正执行前,要先确认这张表的定义还能不能用,于是会在表上加一把元数据锁。
元数据锁按「允许别人做什么」分成几档,面试和工作里最常碰到的是下面三种:
普通的虽然只读行,但编译和执行阶段仍要读到列名、类型这些表定义,所以会申请元数据共享读锁。多个会话可以同时持有这把锁,互不影响。
ALTER、DROP这类要改表结构的语句则必须拿元数据排他锁,同一时刻只允许一个会话修改表定义。别的会话如果还想再加元数据共享读锁或元数据共享写锁,都要先等着,等前面的锁被释放。元数据共享读锁和元数据排他锁不能同时存在:长事务里没提交的一直握着元数据共享读锁,后面的ALTER就拿不到元数据排他锁,语句会一直停在等待状态。
元数据锁的持续时间分三档:
事务里的如果在事务中执行,会持有事务级的元数据共享读锁:语句跑完不会立刻释放,会一直持有到事务提交,才会被释放。元数据锁不走eout,但会受影响,等太久可能超时报错。ALTER拿不到元数据排他锁时,语句会一直等着;你能做的,就是等还一直持有元数据共享读锁的事务提交,或者结束那个会话。

意向锁:IS、IX
意向锁( Lock)是里的一种表级锁。它锁的不是整张表的数据,而是表达一个声明:这个事务打算在表里的某些行上,加什么类型的行锁。
分成两种:
意向锁存在的意义,是让显式表锁(比如LOCK … WRITE拿到的表级X锁)和行级锁能高效共存。事务要锁行时,先在表级加IS或IX,等于告诉后面想加表级锁的操作:这张表里有人在锁行。后续的表级锁请求就能快速判断是否冲突,不必逐行检查每一行上有没有行锁。
有一点容易误会:普通的快照读,层往往不加IS/IX; FOR SHARE加IS,、、和 FOR 加IX。

IS和IX之间都兼容。和显式表锁S、X比:IS和S可以共存,IX和S冲突,IS和IX都不能和X共存。面试时画个兼容矩阵就能说清楚。
LOCK WRITE会同时涉及元数据锁和表锁:元数据层加「禁止读写的共享锁」(模式SNRW),层加表排他X锁(显式表锁,不是意向锁)。日常DML几乎不会显式加表锁S或X,只在真正锁行时才隐式加意向锁。

行级锁:三种精确语义
行级锁不只是简单的共享和排他,还设计了三种精确语义来控制锁的范围。
索引记录在物理存储上是一条链,记录之间有空隙。

隔离级别对行锁影响很大:
对比项
只读已提交RC
可重复读RR
普通
快照读,不加行锁
快照读,不加行锁
当前读加锁范围
多数只锁匹配记录
范围扫描常带间隙
锁释放时机
语句结束释放行锁
事务结束才释放间隙锁
幻读
可能出现
当前读下用间隙锁避免
插入意向锁与隐式锁
注意区分:下面的「插入意向锁」( Lock)和上一节的表级「意向锁」( Lock,IS/IX)是两种不同的锁。英文里都带,但一个是插入时在间隙上等待,一个是表级IS/IX,别混在一块。
语句有一种特殊的锁:插入意向锁。当插入的目标间隙上已有Gap锁时mysql executeupdate 一条UPDATE语句在MySQL 8.0中到底加了几把锁?,插入事务会先加上插入意向锁,然后进入等待。多个事务往同一间隙插入时,它们的插入意向锁不冲突,可以同时等;但它们都要等Gap锁先被释放。所以会出现:读事务握着Gap锁,写事务的在下面排队等着;两个在等同一个Gap时,彼此之间不用互相等。


隐式锁是另一个容易被忽略的设计。未提交的并不立即创建锁对象,而是在聚簇记录上留下。别的事务来读这条记录时,判断是否活跃,活跃才会转换成显式锁。这种设计省内存,发生冲突时才会创建锁对象。

还有N多的锁
比如自增锁,谓词锁,谓词页锁等等。。。。非常的多,但最关键的,还是我们上面提到的,先从架构入手,然后再逐个击破每个锁。
用架构思维回答面试题
面试被问到锁相关的问题,按三层架构来组织答案会更清晰。
MySQL都有哪些锁?
按三层说:层有元数据锁MDL,管表结构能不能动;表级有意向锁IS/IX和自增锁;行级有共享锁、排他锁,以及Next-Key、Gap、三种精确语义,还有插入意向锁和隐式锁。
什么是间隙锁?和Next-Key啥关系?
间隙锁只锁索引记录之间的空隙。Next-Key是记录锁加记录前面的间隙,是可重复读下默认的记录锁形态;Gap是其中的间隙部分。可重复读语境下口头说的行锁,往往指的是Next-Key锁。
可重复读怎么防幻读?
快照读读MVCC版本,不加行锁。在可重复读下mysql executeupdate 一条UPDATE语句在MySQL 8.0中到底加了几把锁?,同一事务的快照读共用读视图,别的事务后来提交的插入,快照读一般看不到。当前读会加Next-Key锁和Gap锁,不让别的事务往间隙里插行,从而减少当前读路径上的幻读。只读已提交下,每次快照读可能看到不同的行数,幻读更容易出现。
意向锁IS/IX有啥用?
让显式表锁和行级锁高效共存。事务在真正锁行前先加IS或IX,等于在表级声明「打算在某些行上加S锁或X锁」。后面如果有人要LOCK 拿表级S或X锁,看一眼表上的意向锁就能判断会不会冲突,不必扫全表检查每一行的锁状态。
元数据锁是什么?为啥删表会一直等着?
元数据锁保护的是表定义,不是行数据。删表要拿元数据排他锁,独占表定义。只要还有会话一直持有该表的元数据锁,DDL语句就会一直在等待状态等着。特别是未提交的长查询,会一直持有元数据共享读锁,不会释放。
死锁怎么产生?怎么查?
两个事务互相等对方持有的锁,形成环。排查看SHOW 里的 ,或的、。检测到环后,会按等规则挑一个事务回滚,不完全是「谁改动少就回滚谁」。
FOR 锁什么?
当前读,层拿元数据共享写锁,层加意向排他锁IX,对命中行加排他锁;可重复读下范围条件可能加Next-Key或Gap。未命中唯一索引等值且记录不存在时可能只锁间隙。
为什么ALTER表一直在等?
先看元数据锁这一层。有长事务一直握着这张表的元数据共享读锁,ALTER要的元数据排他锁就拿不到,语句会一直停在等待状态。和行锁等待不同mysql executeupdatemysql executeupdate,元数据锁不走eout,但受约束,只能等那个事务提交、结束会话,或等到超时。
参考的内容
希望这篇文章可以帮到你。
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299
资源库 - 资源分享下载网 » mysql executeupdate 一条UPDATE语句在MySQL 8.0中到底加了几把锁?
常见问题FAQ
- 关于资源售价和售后服务的说明?
- 代码有没有售后服务和技术支持?
- 有没有搭建服务?
- 链接地址失效了怎么办?
- 关于解压密码

