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出同一表中的某些值 ...
随机推荐
- 记XShell无法连接虚拟机中的Linux,但Linux系统中可以连接外网。
如题. 原本设置如下: 本地机IP 为192.168.43.XXX VMWare中"虚拟机网络编辑器"中子网设置为192.168.39.0. 虚拟机中IP为192.168.39.1 ...
- 抓包工具fiddler使用-初级
参考 https://kb.cnblogs.com/page/130367/#introduce
- 【CF607B】Zuma——区间dp(记忆化搜索/递推)
以下是从中文翻译成人话的题面: 给定一个长度小于等于500的序列,每个数字代表一个颜色,每次可以消掉一个回文串,问最多消几次可以消完? (7.16) 这个题从洛谷pend回来以后显示有103个测试点( ...
- C语言精华——内存管理,很多学校学习不到的知识~
在编写程序时,通常并不知道需要处理的数据量,或者难以评估所需处理数据量的变动程度.在这种情况下,要达到有效的资源利用--使用内存管理,必须在运行时动态地分配所需内存,并在使用完毕后尽早释放不需要的内存 ...
- 论如何优雅的抛出SpringBoot注解的异常
平时我们在写代码的时候肯定要进行很多参数验证,最开始的时候我们一般都是这样处理的 如下图 看起来好像也没什么,但是 如果参数多了呢?你就会看到这样的校验 OMG!!! 有没有感觉稍微有点视觉 ...
- Spring Boot 统一返回结果及异常处理
在 Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 & 异常处理 基础上优化.调整 一.通用类 1.1 通用的返回对象 public class CommonReturn ...
- error: src refspec master does not match any(个人经验)
分支名写错了,推送不到远程 修改本地分支名称 git branch -m oldName newName 再推送到远程就好了
- 第6.4节 Python动态表达式计算:eval函数详述
在Python动态执行的函数中,eval是用于执行表达式计算的函数,这个函数用于执行字符串中包含的一个表达式或其编译后对应的代码,不能适用于执行Python语句和完整的代码. 一. 语法 1. ...
- PyQt(Python+Qt)学习随笔:QMainWindow的splitDockWidget方法将QDockWidget停靠窗分割排列
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 主窗口的splitDockWidget方法用于将一个停靠窗占据的空间分 ...
- 第11.8节 Python正则表达式的重复匹配模式及元字符“?”、 “*”、 “+”功能介绍
符号"?".""."+"这三个元字符修饰符在Python中都表示重复匹配的模式,即要求匹配的字符串满足重复次数的要求,但具体重复次数要求不同 ...