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

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们