Mysql 中的MDL
本文可以结合 MySQL中的事务原理和锁机制 查看。
首先简单了解一下 mysql 的 sql 类型:
1、数据定义语言 DDL:Create、Drop、Alter 操作。用于定义库和表结构的。
2、数据查询语言 DQL:select。用于查询数据的。
3、数据操纵语言 DML:insert、update、delete。对行记录进行增删改操作。
4、数据控制语言 DCL:grant、revoke、commit、rollback。控制数据库的权限和事务。
MDL
MDL(MetaData Lock)就是针对于 DDL 与 DML、DQL 操作加锁,执行 DDL 自动添加写锁,执行 DML、DQL 自动添加读锁,也就是说 DML 语句可以同时执行(不考虑其他锁),而 DDL 间则会相互阻塞。
为什么在执行 DDL 时会添加写锁?
DDL 在执行会先创建一个临时表,先将表的数据全部移到这个临时表中,然后再将临时表替换当前表。在这个过程中如果出现读写操作就会影响最终结果出错。这个过程耗时主要在将原表的数据移到临时表的过程。

执行
不同事务的执行是按队列顺序进行的,如果两个事务所执行的 MDL 添加的分别是读、写锁,那么就会互斥,后面的事务只有等到前面事务提交释放锁后才能执行。
例子:假设有四个会话:session1、session2、session3、session4 ,首先先依次开启事务,然后session1,session2 先执行查询操作(为了避免可能是可串行化级别导致加的写锁冲突,所以就使用查询操作),session1,session2 中的操作可以正常执行,session3执行 Alter 修改表结构,此时 session3 的操作就会阻塞(因为 MDL 的读写锁冲突),session4 再执行增删改查也会被阻塞,因为是在队列中,它位于 session3 后面,所以只有等到 session3 提交后其才能继续执行。
Online DDL
通过上面的分析,进行实践检验,却出现了下面的情况:

可以看到执行和显示顺序是图中标注的从1开始递增按顺序执行的。可以看到 session4 在 session2 提交后就立刻会执行,并且在 session4 提交后 session3 才能执行成功,这个和前面所说的理论就会冲突。这个原因是当前 mysql 版本是5.6,而在 mysql 5.6 支持 Online DDL。
Online DDL 是对 MDL 的一种优化,因为如果按照 MDL 的执行逻辑,像上面这种情况,一旦一些简单的读写操作比某一条 DDL 语句启动慢一些,就会陷入阻塞,如果 DDL 修改的是大表且是高频表,那么在这条语句执行时会阻塞所有的读写操作,很容易使数据库崩溃。而 Online DDL 优化思路就是在获取到锁之后先允许一段时间的读写操作,直到临时表的数据转移完成,再停止其他读写操作,而具体实现就主要分为下面几步,
1. 拿MDL写锁
2. 降级成MDL读锁,接受读写操作,读操作直接正常返回,写操作会被记录下来,等待后面更新到临时表中。
3. 真正做DDL,在 DDL 表记录向临时表转移完成并执行完记录的写操作后开始阻塞读写操作。
4. 升级成MDL写锁,进行临时表的替换
5. 释放MDL锁
应用于上面的例子就是:
1、session1、session2 因为是队列的前两个,先添加MDL读锁,正常执行,session3 因为是要添加 MDL 写锁所以阻塞,session4 在 session3 后面所以也阻塞,session1、session2执行完成提交释放读锁。
2、session3 在获取到 MDL 写锁后,会先进行降级降级成读锁
3、在 session3 降级后 session4 因为是 MDL 读锁,所以也会获取到锁,执行
4、session3 在完成向临时表数据迁移以及执行完记录的写操作后想升级回写锁发现当前的读锁还被 session4 占用,所以会阻塞,等待 session4 执行释放。
5、session4 提交事务,释放读锁,session3 成功升级锁,输出提示语句,最后提交。
如果前面的例子还有一个 session5,并且在一开始和 session4 一起开启事务、查询,那么在 session2 提交后 session5 也会随着 session4 一起执行,而 session3 则需要等待 session4、session5 提交后才能执行第四步。
而如果 session5 开启事务是在 session3 向临时表数据迁移完成后,那么 session5 的查询操作就会被 session3 阻塞,直到 session3 提交事务。
MDL 引发的问题
在上线项目中,如果需要对某个大表的字段进行删除,那么必然会阻塞该表的所有增删改查操作,如果该表存储了热点数据,那么就会阻塞大量的操作,最终导致数据库崩溃。
解决
1、查看当前是否存在长事务,如果存在,先尽快将其提交,防止长事务的MDL写锁阻塞
2、为 DDL 的操作设置过期时间,如果时间内没有成功执行就取消。可以使用 Github 的开源工具 gh-ost。
Mysql 中的MDL的更多相关文章
- MySQL · 特性分析 · MDL 实现分析
http://mysql.taobao.org/monthly/2015/11/04/ 前言 在MySQL中,DDL是不属于事务范畴的,如果事务和DDL并行执行,操作相关联的表的话,会出现各种意想不到 ...
- MySQL实战 | 06/07 简单说说MySQL中的锁
原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...
- 你了解MySQL中的锁吗?
MySQL中的锁,分为全局锁.表级锁.行锁 全局锁 全局锁的意思就是,对整个数据库实例加锁,它的命令是FTWRL Flash tables with read lock 这个命令的语义是,使整个库处于 ...
- 一步一步带你入门MySQL中的索引和锁 (转)
出处: 一步一步带你入门MySQL中的索引和锁 索引 索引常见的几种类型 索引常见的类型有哈希索引,有序数组索引,二叉树索引,跳表等等.本文主要探讨 MySQL 的默认存储引擎 InnoDB 的索引结 ...
- Mysql中的三类锁,你知道吗?
导读 正所谓有人(锁)的地方就有江湖(事务),人在江湖飘,怎能一无所知? 今天来细说一下Mysql中的三类锁,分别是全局锁.表级锁.行级锁. 文章首发于作者公众号[码猿技术专栏],原创不易,喜欢的点个 ...
- 【科普】MySQL中DDL操作背后的并发原理
一. 简介 DQL:指数据库中的查询(select)操作. DML:指数据库中的插入(insert).更新(update).删除(delete)等行数据变更操作. DDL:指数据库中加列(add co ...
- 详述 MySQL 中的行级锁、表级锁和页级锁
转自:https://blog.csdn.net/qq_35246620/article/details/69943011 refer:cnblogs.com/f-ck-need-u/p/899547 ...
- MySQL 中如何定位 DDL 被阻塞的问题
经常碰到开发.测试童鞋会问,线下开发.测试环境,执行了一个DDL,发现很久都没有执行完,是不是被阻塞了?要怎么解决? 包括在群里,也经常会碰到类似问题:DDL 被阻塞了,如何找到阻塞它的 SQL ? ...
- MySQL中You can't specify target table for update in FROM clause一场
mysql中You can't specify target table <tbl> for update in FROM clause错误的意思是说,不能先select出同一表中的某些值 ...
随机推荐
- C3PO数据库连接池
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 -<c3p0-config> 4 5 6 -& ...
- 蓝桥杯——螺旋折线(2018JavaB组第7题19分)
螺旋折线(18JB-7-19') 如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次. 对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度. ...
- SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂)
SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂) Spring Boot Actuator是spring boot项目一个监控模块,提供了很多原生的端点,包含了对应用系统的自 ...
- JZOJ2020年8月11日提高组T2 宝石
JZOJ2020年8月11日提高组T2 宝石 题目 Description 见上帝动了恻隐之心,天后也想显示一下慈悲之怀,随即从口袋中取出一块魔术方巾,让身边的美神维纳斯拿到后堂的屏风上去试试,屏风是 ...
- day7(vue发送短信)
1.vue发送短信逻辑 前端函数如下,js方法代码无需更改,前端代码逻辑在components\common\lab_header.vue 只需要修改components\axios_api\http ...
- linux搭建harbor与使用
条件:安装docker&docker-compose 如未安装,请看:linux离线安装docker + docker-compose harbor 1.下载 下载地址:https://git ...
- 快速理解Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容的区别
<Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容有何不同?>老猿介绍了二者的区别,为了快速理解,老猿在此使用另外一种方式补充说明一下: 1.使用%r是调用objec ...
- PyQt(Python+Qt)学习随笔:QTreeWidgetItem项是否禁用disable、隐藏isHidden和允许选中isSelected
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 树型部件QTreeWidget的项QTreeWidgetItem对象具有是否禁用disable.是否 ...
- PyQt学习随笔:Model/View开发时在view数据项中设置不同角色数据的方法
在往Model中通过QStandardItem等类插入数据项时,除了实际插入的存储数据,还可以设置不同角色(请参考<PyQt学习随笔:Model/View中诸如DisplayRole的数据角色及 ...
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的焦点策略focusPolicy设置
在Qt Designer中可以设置部件的焦点策略,部件的焦点策略属性取值范围由枚举类型Qt.FocusPolicy来定义,该枚举类型及其含义如下表所示: 注意:经老猿测试鼠标轮滚动获取焦点,只有在鼠标 ...