转载

【MySQL】MetaData Lock 之一

一 简介

和MySQL打交道比较多的朋友,肯定遇到过 "Waiting for table metadata lock"或者由于MDL导致的故障,不过本文介绍MDL锁之前,我们先看一个著名的 bug#989 大致情况如下:

session1:

BEGIN; INSERT INTO t ... ; COMMIT;

session2:

DROP TABLE t;

然后上面的操作流程在binlog记录的顺序是

DROP TABLE t; BEGIN; INSERT INTO t ... ; COMMIT;

很显然备库执行binlog时会先删除表t,然后执行insert 会报1032 error,导致复制中断。为了解决该bug,MySQL 在5.5.3引入了MDL锁。

二 metadata lock是什么

顾名思义,metadata lock即 元数据锁 。在数据库中元数据即数据字典信息包括db,table,function,procedure,trigger,event等。metadata lock主要为了保证元数据的一致性,用于处理不同线程操作同一数据对象的同步与互斥问题,如:

session1:

begin ; select * from t1 for update ...

session2:

begin ; alter table t1 add column str varchar(30);

在以上两个事务中,s1 s2都会操作表t1,但由于s1首先获取t1的锁,而s2在获得锁的时候由于互斥,所以只能等待; 

其实5.5也有类似保护元数据的机制,只是没有明确提出MDL概念而已。但是5.5之前版本(比如5.1)与5.5之后版本在保护元数据这块有一个显著的不同点是, 5.1对于元数据的保护是语句级别的,5.5对于metadata的保护是事务级别的 。所谓语句级别,即语句执行完成后,无论事务是否提交或回滚,其表结构可以被其他会话更新;而事务级别则是在事务结束后才释放MDL。引入MDL后,主要解决2个问题:

  1. 事务隔离问题,比如在可重复隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求.
  2. 数据复制问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致slave在重做时,先重做alter,再重做update时就会出现复制错误的现象。也就是简介中提到的bug。

三 小结

本文浅显的介绍MDL的来龙去脉,想比较详细的了解MDL的前生今世的读者请移步@印风的文章 《MySQL metadata lock的前世今生(5.1=>5.7)》

MySQL引入MDL之后 也会带来一定的负面影响 比如 “wait for global read lock” 或者 “wait for table lock” 之类的锁等待,当遇到大查询,同时遇到一个DDL,基本就能造成一个故障了。后面的文章会深入介绍MDL的实现原理和运行机制,加入一些常见的案例和解决方法。

正文到此结束
Loading...