上一篇《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的兼容性矩阵(对象维度)

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

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

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(一)》。这里我们要考虑一个问题,LOCK TABLE ... READ上的MDL锁是MDL_SHARED_READ,而DML操作上的是MDL_SHARED_WRITE,那么前者和后者如何互斥?其实这个MDL是无能为力的,需要通过SERVER层的table lock来解,可以简单做一个实验,一个会话执行LOCK TABLE test READ,另外一个会话执行update test set xxx where id=xxx,会发现update语句堵塞,通过show processlist查看,状态为:"Waiting for table level lock"。但是如果使用LOCK TABLE test WRITE,则状态变为"Waiting for table metadata lock",其实此时table lock也是堵住的,只不过MDL在之前挡住了,这说明SERVER层的table lock和MDL在同时起作用。

mysql metadata lock(二)的更多相关文章

  1. mysql metadata lock(一)

    想必玩过mysql的人对Waiting for table metadata lock肯定不会陌生,一般都是进行alter操作时被堵住了,导致了我们在show processlist 时,看到线程的状 ...

  2. mysql metadata lock(三)

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

  3. mysql metadata lock锁

    很多情况下,很多问题从理论上或者管理上而言都是可以避免或者说很好解决的,但是一旦涉及到现实由于管理或者协调或者规范执行的不够到位,就会出现各种各样本不该出现的问题,这些问题的通常在生产环境并不会出现, ...

  4. 初步认知MySQL metadata lock(MDL)

    http://blog.itpub.net/26515977/viewspace-1208250/ 概述 随着5.5.3引入MDL,更多的Query被“Waiting for table metada ...

  5. mysql metadata lock

    想必玩过mysql的人对Waiting for table metadata lock肯定不会陌生,一般都是进行alter操作时被堵住了,导致了我们在show processlist 时,看到线程的状 ...

  6. MySQL Metadata Lock详解

    Metadata Lock 的作用: 要直接说出Metadata Lock 的作用.以我目前的文字功底是不行的.好在我可以通过一个例子来说明. 假设session 1 在正在执行如下的SQL语句 se ...

  7. Metadata Lock原理5

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

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

    转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for tab ...

  9. 【转】【MySql】Waiting for table metadata lock原因分析

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Wa ...

随机推荐

  1. 【C#进阶系列】20 异常和状态管理

    异常就是指成员没有完成它的名称所宣示的行动. public class Girl { public string Name { get; set; } } public class Troy{ Gir ...

  2. thinkphp中assign()和display()区别和用法

  3. How to return dictionary keys as a list in Python 3.3

    http://btmiller.com/2015/04/13/get-list-of-keys-from-dictionary-in-python-2-and-3.html Get a List of ...

  4. Delphi Berlin 10.1 for 小米平板2 (Win 10) 电子罗盘测试

    Windows 10 下没有 Sensor.HeadingXSensor.HeadingYSensor.HeadingZ 需改用 Sensor.CompMagHeading

  5. jquery easyui 弹出消息框 (转载) jQuery EasyUI API 中文文档 - 消息框(Messager) http://www.cnblogs.com/hantianwei/archive/2012/03/19/2407113.html

    <html> <head> <!-- 导入easyui插件的js和css样式; --> <link rel="stylesheet" ty ...

  6. mysql 导入text 到数据库

    load data local infile 'f:/PhoneLocation_201601.327665.txt' into table sys_t_phone_area fields termi ...

  7. java三种实现线程的方法比较

    1.继承Thread 2.实现Runnable 1和2的比较,1可以创建不同的任务,每个任务互不干扰,对于2,相当于只执行一个任务,多个任务之间互相影响,比如售票系统,每售出一张票,票数都要减1,这个 ...

  8. 使用loadrunner进行压力测试之----post请求

    1. 发送post请求时使用web_submit_data 如: web_submit_data("create",//事务名 "Action=http://bizhi. ...

  9. MyBatis入门(一)

    一.MyBaris简介 1)MyBaris发展过程 MyBatis的前身叫iBatis,本是apache的一个开源项目, 2010年这个项目由apache software foundation 迁移 ...

  10. linux非常用但很有用的命令

    查找指定目录下包含指定字符串的所有文件 grep -rl 'abc' / top查看命令的完整启动路径 top 按c top以MB为单位显示内存信息 top -M 查看内存top io趋势 pidst ...