一 简介 
  上一篇文章 《MetaData Lock 之一》  简单的介绍了MySQL 引入MDL 的前因后果,本文深入了解MDL的实现原理和运行机制。
二 MDL 的类型
  metadata lock也是一种锁。每个metadata lock都会定义锁住的对象,锁的持有时间和锁的类型。
2.1 按照对象/范围划分

属性 含义 范围/对象
GLOBAL 全局锁 范围
COMMIT 提交保护锁 范围
SCHEMA 库锁 对象
TABLE 表锁 对象
FUNCTION 函数锁 对象
PROCEDURE 存储过程锁 对象
TRIGGER 触发器锁 对象
EVENT 事件锁 对象

MDL按锁住的对象来分类,可以分为global,commit,schema, table, function,procedure,trigger,event,这些对象发生锁等待时,我们在show processlist可以分别看到如下等待信息。

  1. Waiting for global read lock
  2. Waiting for commit lock
  3. Waiting for schema metadata lock
  4. Waiting for table metadata lock
  5. Waiting for stored function metadata lock
  6. Waiting for stored procedure metadata lock
  7. Waiting for trigger metadata lock
  8. Waiting for event metadata lock

2.2 按照锁的持有时间

属性 含义
MDL_STATEMENT 从语句开始执行时获取,到语句执行结束时释放。
MDL_TRANSACTION 在一个事务中涉及所有表获取MDL,一直到事务commit或者rollback(线程中终清理)才释放。
MDL_EXPLICIT 需要MDL_context::release_lock()显式释放。
语句或者事务结束,也仍然持有,如
Lock table, flush .. with lock语句等。

2.3 按照操作的对象

属性 含义 事例
MDL_INTENTION_EXCLUSIVE(IX) 意向排他锁用于global和commit的加锁。 truncate table t1;
insert into t1 values(3,'abcde');会加如下锁(GLOBAL,MDL_STATEMENT,MDL_INTENTION_EXCLUSIVE)                            (SCHEMA,MDL_TRANSACTION,MDL_INTENTION_EXCLUSIVE)

MDL_SHARED(S) 只访问元数据 比如表结构,不访问数据。 set golbal_read_only =on 加锁
(GLOBAL,MDL_EXPLICIT,MDL_SHARED)
MDL_SHARED_HIGH_PRIO(SH) 用于访问information_scheam表,不涉及数据。 select * from information_schema.tables;
show create table xx; desc xxx;会加如下锁:
(TABLE,MDL_TRANSACTION,MDL_SHARED_HIGH_PRIO)
MDL_SHARED_READ(SR) 访问表结构并且读表数据 select * from t1; lock table t1 read;
会加如下锁:
(TABLE,MDL_TRANSACTION,MDL_SHARE_READ)
MDL_SHARED_WRITE(SW) 访问表结构并且写表数据 insert/update/delete/select .. for update
会加如下锁:
(TABLE,MDL_TRANSACTION,MDL_SHARE_WRITE)
MDL_SHARED_UPGRADABLE(SU) 是mysql5.6引入的新的metadata lock,
在alter table/create index/drop index会加该锁;可以说是为了online ddl才引入的。特点是允许DML,防止DDL;
(TABLE,MDL_TRANSACTION,MDL_SHARED_UPGRADABLE)
MDL_SHARED_NO_WRITE(SNW) 可升级锁,访问表结构并且读写表数据,并且禁止其它事务写。 alter table t1 modify c bigint;(非onlineddl)
(TABLE,MDL_TRANSACTION,MDL_SHARED_NO_WRITE)
MDL_SHARED_NO_READ_WRITE(SNRW) 可升级锁,访问表结构并且读写表数据,并且禁止其它事务读写。 lock table t1 write;加锁
(TABLE,MDL_TRANSACTION,MDL_SHARED_NO_READ_WRITE
MDL_EXCLUSIVE(X) 防止其他线程读写元数据 CREATE/DROP/RENAME TABLE,其他online DDL在rename阶段也持有X锁
(TABLE,MDL_TRANSACTION,MDL_EXCLUSIVE)

关于global对象
   主要作用是防止DDL和写操作的过程中,执行set golbal_read_only =on或flush tables with read lock;
 关于commit对象锁
  主要作用是执行flush tables with read lock后,防止已经开始在执行的写事务提交。
  insert/update/delete在提交时都会上(COMMIT,MDL_EXPLICIT,MDL_INTENTION_EXCLUSIVE)锁。

 

2.4 MDL 锁的兼容性矩阵

三、几种典型语句的加(释放)锁流程
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锁,大部分情况都是线上DB出现异常了。那么出现异常后,我们如何去判断是MDL锁导致的呢。监视MDL锁主要有两种方法,一种是通过show  processlist命令,判断是否有事务处于“Waiting for table metadata lock”状态,另外就是通过mysql的profile,分析特定语句在每个阶段的耗时时间。
抛出几个问题:
select 与alter是否会相互阻塞
dml与alter是否会相互阻塞
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阶段。
第三个问题,显然,由于MDL_SHARED_WRITE与MDL_SHARED_READ兼容,所以它们不会因为MDL而导致等待的情况。

五 参考资料
 [1] 《MDL 锁介绍二 》他的三篇文章都值得一读,强烈推荐,本系列文章也是参考他的blog 写的。
 [2] 《DDL操作导致备库复制中断》 @印风的blog 为alisql/RDS 打了N多patch的牛人。

Metadata Lock原理6的更多相关文章

  1. Metadata Lock原理5

    [MySQL] 之一2015-09-05 15:46:51 分类: MySQL 一 简介 和MySQL打交道比较多的朋友,肯定遇到过 "Waiting for table metadata ...

  2. Metadata Lock原理4

     http://blog.chinaunix.net/uid-28212952-id-3400571.html    Alibaba  今天发生一个故障,MM复制结构(主备库),备库slave del ...

  3. Metadata Lock原理8

    http://www.kancloud.cn/taobaomysql/monthly/67141 MySQL· 5.7优化·Metadata Lock子系统的优化 背景 引入MDL锁的目的,最初是为了 ...

  4. Metadata Lock原理7

    http://blog.itpub.net/22664653/viewspace-1791744/ 一 简介 通过前面两篇文章的介绍,相信读到这里的各位对MDL 锁已经有了比较深入的了解了,本文将结合 ...

  5. Metadata Lock原理3

      http://blog.itpub.net/26515977/viewspace-1208250/   腾讯工程师 随着5.5.3引入MDL,更多的Query被“Waiting for table ...

  6. Metadata Lock原理2

    同事说开发机更改一个表结构,加字段,但是一直挂在那里,没反应.一开始以为表测试数据量很大,因为mysql增加表字段会重写表,后来看了下数据量很小,就另外查看过程.原因分析和处理如下:  一.环境  m ...

  7. Metadata Lock原理1

    https://www.percona.com/blog/2013/02/01/implications-of-metadata-locking-changes-in-mysql-5-5/ impli ...

  8. mysql metadata lock(三)

    前言 MDL锁主要用来保护Mysql内部对象的元数据,通过MDL机制保证DDL与DML以及SELECT查询操作的并发.MySQL Meta Lock(一)和MySQL Meta Lock(二)已经讲了 ...

  9. mysql metadata lock(二)

    上一篇<mysql metadata lock(一)>介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问.本文将更详细的介绍MDL,主要 ...

随机推荐

  1. 1、ListView自定义控件下拉刷新(一)

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layo ...

  2. 在word中显示漂亮的代码

    在word中粘贴或写代码时,通常得不到想要的格式,可用‘Notepad++’工具实现. 步骤: (1)安装Notepad++软件,把代码粘贴进去,选择菜单栏中的语言,然后选择相应代码语言,如P-> ...

  3. 扩展Fitnesse的ScriptTable:支持if-then

    Fitnesse的ScriptTable只能顺序执行所有行,本博文介绍如何让ScriptTable支持if-then,来条件执行一行. 首先普及一下概念,什么是Fitnesse,听一听.NET版Cuc ...

  4. Clang Language Extensions

    Xcode 本文是自<Clang Language Extensions> 中选取部分与 Objective-C 相关的内容翻译,由于作者水平有限,如存在理解错误或翻译不到位的地方,还请指 ...

  5. .net,mvc使用bootstrap做一个标准后台

    今天准备搭一个公用后台,使用bootstrap,方便今后开发,顺便mark一下 后期列表页将使用kendo-ui,增强后台的效果 下面是代码... login页面 @{ Layout = null; ...

  6. hadoop多次格式化后,导致datanode启动不了,怎么办?(伪分布式)

    根据当初 hadoop 安装目录下 conf 目录的 core-site.xml 的设置,找到该目录:   进入该目录 在 data 和 name 文件夹下均有  current 文件夹 ,和 cur ...

  7. homework-07

    终于等到了一次难度相对比较小的问题,只要读完提问题就好,但又不得不说自己真的很菜,且不说C++掌握的不好,连英文也比较差,导致读的非常吃力,不过我还是坚持读完了四篇英文文章,大致意思是可以了解的,但是 ...

  8. (转)定制iOS 7中的导航栏和状态栏

    近期,跟大多数开发者一样,我也正忙于对程序进行升级以适配iOS 7.最新的iOS 7外观上有大量的改动.从开发者的角度来看,导航栏和状态栏就发生了明显的变化.状态栏现在是半透明的了,这也就意味着导航栏 ...

  9. 删除MySQL重复数据

    删除MySQL重复数据 项目背景 在最近做的一个linux性能采集项目中,发现线程的程序入库很慢,再仔细定位,发现数据库里面很多冗余数据.因为在采集中,对于同一台设备,同一个时间点应该只有一个数据,然 ...

  10. display:none;与visibility:hidden;的区别

    visibility:隐藏对应的元素但不挤占该元素原来的空间.display:隐藏对应的元素并且挤占该元素原来的空间. 下面来看visibility和dispaly的一些参数 visibility用来 ...