Metadata Lock原理6
上一篇文章 《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可以分别看到如下等待信息。
- Waiting for global read lock
- Waiting for commit lock
- Waiting for schema metadata lock
- Waiting for table metadata lock
- Waiting for stored function metadata lock
- Waiting for stored procedure metadata lock
- Waiting for trigger metadata lock
- 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的更多相关文章
- Metadata Lock原理5
[MySQL] 之一2015-09-05 15:46:51 分类: MySQL 一 简介 和MySQL打交道比较多的朋友,肯定遇到过 "Waiting for table metadata ...
- Metadata Lock原理4
http://blog.chinaunix.net/uid-28212952-id-3400571.html Alibaba 今天发生一个故障,MM复制结构(主备库),备库slave del ...
- Metadata Lock原理8
http://www.kancloud.cn/taobaomysql/monthly/67141 MySQL· 5.7优化·Metadata Lock子系统的优化 背景 引入MDL锁的目的,最初是为了 ...
- Metadata Lock原理7
http://blog.itpub.net/22664653/viewspace-1791744/ 一 简介 通过前面两篇文章的介绍,相信读到这里的各位对MDL 锁已经有了比较深入的了解了,本文将结合 ...
- Metadata Lock原理3
http://blog.itpub.net/26515977/viewspace-1208250/ 腾讯工程师 随着5.5.3引入MDL,更多的Query被“Waiting for table ...
- Metadata Lock原理2
同事说开发机更改一个表结构,加字段,但是一直挂在那里,没反应.一开始以为表测试数据量很大,因为mysql增加表字段会重写表,后来看了下数据量很小,就另外查看过程.原因分析和处理如下: 一.环境 m ...
- Metadata Lock原理1
https://www.percona.com/blog/2013/02/01/implications-of-metadata-locking-changes-in-mysql-5-5/ impli ...
- mysql metadata lock(三)
前言 MDL锁主要用来保护Mysql内部对象的元数据,通过MDL机制保证DDL与DML以及SELECT查询操作的并发.MySQL Meta Lock(一)和MySQL Meta Lock(二)已经讲了 ...
- mysql metadata lock(二)
上一篇<mysql metadata lock(一)>介绍了为什么引入MDL,MDL作用以及MDL锁导致阻塞的几种典型场景,文章的最后还留下了一个小小的疑问.本文将更详细的介绍MDL,主要 ...
随机推荐
- 【JSONCpp】简介及demo
一.JSON简介 JSON 一种轻量级的数据交换格式,易于阅读.编写.解析,全称为JavsScript ObjectNotation. JSON由两种基本结构组成 ① 名字/值 对的集合,可以理解 ...
- cocos2d-x 详解之 CCLayer(触摸事件)
CCLayer继承自CCNode,在CCLayer中可以实现单点触摸.多点触摸和重力感应回调3种不同形式的交互.这部分的难点在于,当存在多个层都要去接收触摸时它的响应机制是如何处理的.了解内部的处理机 ...
- 你今天Python了吗?(下)
在体验了wxPython的强大之后,让我们把注意力集中到Twisted上来.在C++的世界里,你会发现一个很棒的网络应用框架,那就是ACE了:在Python的地盘,Twisted则是在网络应用框架中当 ...
- Android Environment 类详解
Android应用开发中,常使用Environment类去获取外部存储目录,在访问外部存储之前一定要先判断外部存储是否已经是可使用(已挂载&可使用)状态, 并且需要在AndroidManife ...
- 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇04:碰撞检测》
4.碰撞检测 碰撞概述: 游戏世界里,游戏对象不能做出如同在真实世界里的物理运动效果.对于大部分游戏来说,都要为其添加物理系统,让其可以模拟真实世界发生的物理运动.但是在这个打飞机游戏Demo中,是用 ...
- mapreduce的调度算法和job调优
调度算法: mapreduce当有很多的作业在执行的时候,是按照什么顺序去执行的? 调度算法顺序需要关注: 1.提高作业的吞吐量. 2.要考虑优先级. 三种调度器:如果作业跑不完,并且机器资源利用率比 ...
- HttpServletRequest 的使用
1. 从HttpServletRequest中读取请求参数 InputStream inStream = request.getInputStream(); ByteArrayOutputStream ...
- 转】Apache解决高并发和高可用
原博主于: http://www.ha97.com/5803.html 感谢! 服务器集群 Apache 和 nginx(web服务器) 1. 多台集群机器联合处理一个任务. 2. 一台机器处 ...
- homework-附加题:第12章基本数据类型阅读总结
基本数据类型是构建其他所有数据类型的构造块,本人认为这部分是计算机编程的基础,值得得到大家的注意. 首先,在本章中作者提到了避免使用magic number.使用magic number这种做法是极其 ...
- DB2 递归查询
上一篇中讲解了ORACLE中的递归查询,下面我们看一下DB2中如何使用递归查询: 同样的我们先新建一个表来存储以上信息,并插入测试数据: --建表 create table FAMILY ( pers ...