遇到MySQL MDL锁,如何分析和处理?

之前遇到一个DBA,在生产库上加字段,导致数据库连接数打满。原因就是MDL锁引起。下面让我来介绍一下MDL锁及其排查和处理方式。


MDL锁:全称meta data lock,是表锁,用于保护数据库对象定义不被修改。执行SQL语句操作表都是需要获取和持有MDL锁,直到锁被释放。

在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

  • 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
  • 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。


案例描述:一位同学查询只有2条数据的test.tt1,10秒后却返回锁等待超时报错。

案例警示:

  1. 要对生产数据库有敬畏之心
  2. 业务高峰,不建议对大表和热表做DDL变更(推荐gh-ost)
  3. 有效的数据库备份,重于一切
  4. 良好的数据库运维规范是减少故障的基础(DBA风险操作,需要审核和通知业务方)

技术回放:数据库版本、表结构和报错信息,如下

mysql> select version(); +---------------+ | version() | +---------------+ | 5.7.38-41-log | +---------------+ 1 row in set (0.54 sec) mysql> show create table tmp_mdl_lock ; +--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | tmp_mdl_lock | CREATE TABLE `tmp_mdl_lock` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 | +--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select * from test.tmp_mdl_lock; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction