mysql metadata lock(二)

上一篇《mysql metadata lock(一)》介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问。本文将更详细的介绍MDL,主要侧重介绍MDL的原理和实现。一般而言,商业数据库系统实现锁,一般将锁划分为读锁(共享锁)和写锁(排它锁),为了进一步提高并发性,还会加入意向共享锁和意向排它锁。但是偏偏mysql的MDL搞地比较复杂,但目的也是为了提高并发度。MDL包含有9种类型,详细参考表1。主要其实也是两大类,只是对共享锁做了进一步细分。

一、MDL的锁类型


锁名称


锁类型


说明


适用语句


MDL_INTENTION_EXCLUSIVE


共享锁


意向锁,锁住一个范围


任何语句都会获取MDL意向锁,

然后再获取更强级别的MDL锁。


MDL_SHARED


共享锁,表示只访问表结构


MDL_SHARED_HIGH_PRIO


共享锁,只访问表结构


show create table 等

只访问INFORMATION_SCHEMA的语句


MDL_SHARED_READ


访问表结构并且读表数据


select语句

LOCK TABLE ...  READ


MDL_SHARED_WRITE


访问表结构并且写表数据


SELECT ... FOR UPDATE

DML语句


MDL_SHARED_UPGRADABLE


可升级锁,访问表结构并且读写表数据


Alter语句中间过程会使用


MDL_SHARED_NO_WRITE


可升级锁,访问表结构并且读写表数据,并且禁止其它事务写。


Alter语句中间过程会使用


MDL_SHARED_NO_READ_WRITE


可升级锁,访问表结构并且读写表数据,并且禁止其它事务读写。


LOCK TABLES ... WRITE


MDL_EXCLUSIVE


写锁


禁止其它事务读写。


CREATE/DROP/RENAME TABLE等DDL语句。

                    表1

二、MDL的兼容性矩阵


IX


S


SH


SR


SW


SU


SNW


SNRW


X


IX


1


1


1


1


1


1


1


1


1


S


1


1


1


1


1


1


1


1


0


SH


1


1


1


1


1


1


1


1


0


SR


1


1


1


1


1


1


1


0


0


SW


1


1


1


1


1


1


0


0


0


SU


1


1


1


1


1


1


0


0


0


SNW


1


1


1


1


0


0


0


0


0


SNRW


1


1


1


0


0


0


0


0


0


X


1


0


0


0


0


0


0


0


0

说明:横向表示其它事务已经持有的锁,纵向表示事务想加的锁

三、几种典型语句的加(释放)锁流程

1.select语句操作MDL锁流程

1)Opening tables阶段,加共享锁

a)   加MDL_INTENTION_EXCLUSIVE锁

b)   加MDL_SHARED_READ锁

2)事务提交阶段,释放MDL锁

a)   释放MDL_INTENTION_EXCLUSIVE锁

b)   释放MDL_SHARED_READ锁

2. DML语句操作MDL锁流程

1)Opening tables阶段,加共享锁

a)   加MDL_INTENTION_EXCLUSIVE锁

b)   加MDL_SHARED_WRITE锁

2)事务提交阶段,释放MDL锁

a)   释放MDL_INTENTION_EXCLUSIVE锁

b)   释放MDL_SHARED_WRITE锁

3. alter操作MDL锁流程

1)Opening tables阶段,加共享锁

a)   加MDL_INTENTION_EXCLUSIVE锁

b)   加MDL_SHARED_UPGRADABLE锁,升级到MDL_SHARED_NO_WRITE锁

2)操作数据,copy data,流程如下:

a)   创建临时表tmp,重定义tmp为修改后的表结构

b)   从原表读取数据插入到tmp表

3)将MDL_SHARED_NO_WRITE读锁升级到MDL_EXCLUSIVE锁

a)   删除原表,将tmp重命名为原表名

4)事务提交阶段,释放MDL锁

a)   释放MDL_INTENTION_EXCLUSIVE锁

b)   释放MDL_EXCLUSIVE锁

四、典型问题分析。

一般而言,我们关注MDL锁,大部分情况都是线上出现异常了。那么出现异常后,我们如何去判断是MDL锁导致的呢。监视MDL锁主要有两种方法,一种是通过show  processlist命令,判断是否有事务处于“Waiting for table metadata lock”状态,另外就是通过mysql的profile,分析特定语句在每个阶段的耗时时间。

抛出几个问题:

  1. select 与alter是否会相互阻塞
  2. dml与alter是否会相互阻塞
  3. select与DML是否会相互阻塞

结合第三节几种语句的上锁流程,我们很容易得到这三个问题的答案。语句会在阻塞在具体某个环节,可以通过profile来验证我们的答案是否正确。

第一个问题,当执行select语句时,只要select语句在获取MDL_SHARED_READ锁之前,alter没有执行到rename阶段,那么select获取MDL_SHARED_READ锁成功,后续有alter执行到rename阶段,请求MDL_EXCLUSIVE锁时,就会被阻塞。rename阶段会持有MDL_EXCLUSIVE锁,但由于这个过程时间非常短(大头都在copy数据阶段),并且是alter的最后一个阶段,所以基本感觉不到alter会阻塞select语句。由于MDL锁在事务提交后才释放,若线上存在大查询,或者存在未提交的事务,则会出现ddl卡住的现象。这里要注意的是,ddl卡住后,若再有select查询或DML进来,都会被堵住,就会出现threadrunning飙高的情况。

第二个问题,alter在opening阶段会将锁升级到MDL_SHARED_NO_WRITE,rename阶段再将升级为MDL_EXCLUSIVE,由于MDL_SHARED_NO_WRITE与MDL_SHARED_WRITE互斥,所以先执行alter或先执行DML语句,都会导致语句阻塞在opening tables阶段。结合第一个和第二个问题,就可以回答《mysql metadata lock(一)》的疑问了。

第三个问题,显然,由于MDL_SHARED_WRITE与MDL_SHARED_READ兼容,所以它们不会因为MDL而导致等待的情况。具体例子和profile分析可以参考《mysql metadata lock(一)》。

时间: 2024-08-11 04:31:17

mysql metadata lock(二)的相关文章

MySQL metadata lock

什么是元数据 描述数据库中的数据的数据都是元数据,如库名.表明.列名.版本名,和show语句展示的大多数内容都是元数据,以及在information_shema中记录数据库对象的表中的内容也是元数据 为什么MySQL要设置元数据锁 为了保证可以并发访问数据库对象及保证数据的一致性,所以应用metadata lock,如session1正在扫描t表数据,此会话持有t表的元数据锁,这时session2话尝试要drop t表,在尝试获取t表元数据锁的时候被阻塞,假如没有MDL的设计,那么在sessio

mysql metadata lock锁

很多情况下,很多问题从理论上或者管理上而言都是可以避免或者说很好解决的,但是一旦涉及到现实由于管理或者协调或者规范执行的不够到位,就会出现各种各样本不该出现的问题,这些问题的通常在生产环境并不会出现,但是现实是无论在任何环节出现,都得去找到解决方法,很多时候原因是一部分,预防措施也是一部分,但解决方法也是必须的,因为不可能跟所有的开发人员说你按照我说的做就没有问题了,因为总会有人疏忽了或者忽视了. 前两天,测试环境升级脚本,跑到一半就报锁超时了,好几次后测试让协助而解决下.看了下,是个trunc

MySQL metadata lock阻塞问题

2017年4月1日星期六 在某个业务的主库加完2个字段后,业务方反馈在30分钟后从库也一直无法查看到这个新字段. 在slave上执行show slave status\G 如下图 show porcesslist; 如下图: 上图2张图,可以看到延迟较大,从库上的alter操作一直在等待metadata lock,处于阻塞状态. 解决方法: 使用SELECT * FROM information_schema.innodb_trx\G找到那个事务未提交导致的问题: kill2359; 杀掉这个线

MySQL出现Waiting for table metadata lock的原因以及解决方法

转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for

【MySQL经典案例分析】 Waiting for table metadata lock

本文由云+社区发表 一. 问题是这样来的 ? 2018年某个周末,接到连续数据库的告警,告警信息如下: 二. 苦逼的探索过程 1.总体的思路 看到too many connection的报错信息,基本上可以把问题定位在: (1)机器负载飙升,导致SQL执行效率下降,导致连接推积 (2)业务访问量突增(或者有SQL注入现象),导致连接数打满 (3)出现"死锁"或者锁竞争严重,导致大量SQL堆积 2.排查过程 (1)机器的各项性能指标都显示正常, 没有出现高负载现象,暂时先排除了这种原因

MySQL出现Waiting for table metadata lock的原因以及解决方法(转)

MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列.如果是产品环境的核心表出现了这样的锁等待队列,就会造成

RDS MySQL 表上 Metadata lock 的产生和处理

1. Metadata lock wait 出现的场景 2. Metadata lock wait 的含义 3. 导致 Metadata lock wait 等待的活动事务 4. 解决方案 5. 如何避免出现长时间 Metadata lock wait 导致表上相关查询阻塞,影响业务 1. Metadata lock wait 出现的场景 创建.删除索引 修改表结构 表维护操作(optimize table.repair table 等) 删除表 获取表上表级写锁 (lock table tab

Mysql事物与Metadata lock 问题

环境说明: MySQL 5.6.16 OS:Linux RedHat 6.2 64bit 1.问题描述 目前新上一个使用MySQL数据库项目,在数据库中,每隔5分钟做truncate某个表操作,经常出现metadata lock锁等待,导致后面的对这个表的所有操作(包括读)全部metadata lock等待.严重影响了数据库运行. 且metadata lock锁等待不同于普通的行级锁,等待超时时间默认为365天,而普通的行级锁超时是120s mysql> show variables like

关于mysql的metadata lock

昨天晚上上线,却发现一个ddl语句长时间没有生效 查processlist, 发现包括ddl语句在内的众多查询提示 “Waiting for table metadata lock” 唯一没有该提示的查询为一个全表查询,并且Time项数值最大. kill掉这个查询的线程,后面的ddl语句正常进行了 之前一直听说metadata lock,就是元数据锁,也叫字典锁或者表结构锁.但是没有遇到过. 后来又试了一下——只要在session1里有未完成的增删查改事务,如果在另一个session2中出现加表