Mysql 中的MDL

本文能够结合 MySQL中的事务原理和锁机制 查看。html

首先简单了解一下 mysql 的 sql 类型:mysql

一、数据定义语言 DDL:Create、Drop、Alter 操做。用于定义库和表结构的。sql

二、数据查询语言 DQL:select。用于查询数据的。数据库

三、数据操纵语言 DML:insert、update、delete。对行记录进行增删改操做。session

四、数据控制语言 DCL:grant、revoke、commit、rollback。控制数据库的权限和事务。工具

MDL

MDL(MetaData Lock)就是针对于 DDL 与 DML、DQL 操做加锁,执行 DDL 自动添加写锁,执行 DML、DQL 自动添加读锁,也就是说 DML 语句能够同时执行(不考虑其余锁),而 DDL 间则会相互阻塞。优化

为何在执行 DDL 时会添加写锁?

DDL 在执行会先建立一个临时表,先将表的数据所有移到这个临时表中,而后再将临时表替换当前表。在这个过程当中若是出现读写操做就会影响最终结果出错。这个过程耗时主要在将原表的数据移到临时表的过程。spa

 

执行

不一样事务的执行是按队列顺序进行的,若是两个事务所执行的 MDL 添加的分别是读、写锁,那么就会互斥,后面的事务只有等到前面事务提交释放锁后才能执行。htm

例子:假设有四个会话:session一、session二、session三、session4 ,首先先依次开启事务,而后session1,session2 先执行查询操做(为了不多是可串行化级别致使加的写锁冲突,因此就使用查询操做),session1,session2 中的操做能够正常执行,session3执行 Alter 修改表结构,此时 session3 的操做就会阻塞(由于 MDL 的读写锁冲突),session4 再执行增删改查也会被阻塞,由于是在队列中,它位于 session3 后面,因此只有等到 session3 提交后其才能继续执行。blog

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锁

应用于上面的例子就是:

一、session一、session2 由于是队列的前两个,先添加MDL读锁,正常执行,session3 由于是要添加 MDL 写锁因此阻塞,session4 在 session3 后面因此也阻塞,session一、session2执行完成提交释放读锁。

二、session3 在获取到 MDL 写锁后,会先进行降级降级成读锁

三、在 session3 降级后 session4 由于是 MDL 读锁,因此也会获取到锁,执行

四、session3 在完成向临时表数据迁移以及执行完记录的写操做后想升级回写锁发现当前的读锁还被 session4 占用,因此会阻塞,等待 session4 执行释放。

五、session4 提交事务,释放读锁,session3 成功升级锁,输出提示语句,最后提交。

注意:

一、若是前面的例子还有一个 session5,而且在一开始和 session4 一块儿开启事务、查询,那么在 session2 提交后 session5 也会随着 session4 一块儿执行,而 session3 则须要等待 session四、session5 提交后才能执行第四步。

  而若是 session5 开启事务是在 session3 向临时表数据迁移完成后,那么 session5 的查询操做就会被 session3 阻塞,直到 session3 提交事务。

二、Online DDL 整个过程是在 InnoDB 内部执行的,对于 Server 来讲并无什么操做,因此这个操做是 "inplace" 的,也就是说:

  Online 过程必定是 inplace 的,但 inplace 过程不必定是 Online 的。

三、5.6 开始由于支持 Online DDL,因此在向临时表迁移数据时可能会积攒一些写操做形成页分裂,同时在建立新表时每一个数据页还会留 1/16 的空间用于更新操做,因此执行DDL后的表结构不必定是最 "紧凑" 的。

 

 

MDL 引起的问题

在上线项目中,若是须要对某个大表的字段进行删除,那么必然会阻塞该表的全部增删改查操做,若是该表存储了热点数据,那么就会阻塞大量的操做,最终致使数据库崩溃。

解决

一、查看当前是否存在长事务,若是存在,先尽快将其提交,防止长事务的MDL写锁阻塞
二、为 DDL 的操做设置过时时间,若是时间内没有成功执行就取消。可使用 Github 的开源工具 gh-ost。

相关文章
相关标签/搜索