MySQL中找出谁持有MDL锁

Posted 运维之美

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL中找出谁持有MDL锁相关的知识,希望对你有一定的参考价值。

一、MDL锁的介绍


mysql 5.7版本之前并没有提供一个方便的途径来查看MDL锁,github上有一名为mysql-plugin-mdl-info的项目,通过插件的方式来查看,于是在MySQL 5.7中的performance_schea库下新增了一张表metadata_locks,用其来查看MDL锁那是相当的方便:


不过默认PS并没有打开此功能,需要手工将wait/lock/metadata/sql/mdl监控给打开:


UPDATE performance_schema.setup_consumers SET ENABLED = \'YES\' WHERE NAME =\'global_instrumentation\';

UPDATE performance_schema.setup_instruments SET ENABLED = \'YES\' WHERE NAME =\'wait/lock/metadata/sql/mdl\';


目前MDL有如下锁模式:


锁模式 对应SQL
MDL_INTENTION_EXCLUSIVE GLOBAL对象、SCHEMA对象操作会加此锁
MDL_SHARED FLUSH TABLES with READ LOCK
MDL_SHARED_HIGH_PRIO 仅对MyISAM存储引擎有效
MDL_SHARED_READ SELECT查询
MDL_SHARED_WRITE DML语句
MDL_SHARED_WRITE_LOW_PRIO 仅对MyISAM存储引擎有效
MDL_SHARED_UPGRADABLE ALTER TABLE
MDL_SHARED_READ_ONLY LOCK xxx READ
MDL_SHARED_NO_WRITE FLUSH TABLES xxx,yyy,zzz READ
MDL_SHARED_NO_READ_WRITE FLUSH TABLE xxx WRITE
MDL_EXCLUSIVE ALTER TABLE xxx PARTITION BY …

root@tidb06 08:33:  [test001]> select *  from performance_schema.setup_instruments WHERE NAME =\'wait/lock/metadata/sql/mdl\';
+----------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+----------------------------+---------+-------+
| wait/lock/metadata/sql/mdl | YES | YES |
+----------------------------+---------+-------+
1 row in set (0.00 sec)

root@tidb06 08:44: [test001]> select * from performance_schema.setup_consumers where NAME =\'global_instrumentation\';
+------------------------+---------+
| NAME | ENABLED |
+------------------------+---------+
| global_instrumentation | YES |
+------------------------+---------+
1 row in set (0.00 sec)


二、模拟MDL锁


演示环境:mysql5.7.22  

为了演示 下面参数设置时间如下:


innodb_lock_wait_timeout=600
interactive_timeout = 600
wait_timeout =600


创建测试表和插入测试数据:


CREATE TABLE `test001` (

`id` int(8) NOT NULL AUTO_INCREMENT,

`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,

`password` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,

`create_time` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci


insert into test001(username,password,create_time)value(\'小花\',\'abc123\',now());
insert into test001(username,password,create_time)value(\'王五\',\'ccc123\',now());


 

会话1 开启事务更新1条sql:


\'tidb03\' root@localhost 09:04:56 test001>begin;

Query OK, 0 rows affected (0.00 sec)



\'tidb03\' root@localhost 09:05:03 test001>update test001 set username=\'zhangsan\' where id=2;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0



会话2  更新同一个记录: 产生行锁等待

\'tidb03\' root@localhost 12:40:02 test001>update test001 set username=\'王五\' where id=2;


会话3  给test001表添加索引 : 产生DML表锁等待


\'tidb03\' root@localhost 12:42:36 test001>alter table test001 add index idx_username(username);



会话4  给test001表删除id=2的记录数:同样产生MDL锁等待

\'tidb03\' root@localhost 12:42:42 (none)>show full processlist;

+--------+------+-----------------+---------+---------+------+---------------------------------+------------------------------------------------------+

| Id | User | Host | db | Command | Time | State | Info |

+--------+------+-----------------+---------+---------+------+---------------------------------+------------------------------------------------------+

| 134004 | root | localhost:40418 | test001 | Sleep | 111 | | NULL |

| 134122 | root | localhost:40806 | test001 | Query | 89 | updating | update test001 set username=\'王五\' where id=2 |

| 134336 | root | localhost:41542 | test001 | Query | 14 | Waiting for table metadata lock | alter table test001 add index idx_username(username) |

| 134384 | root | localhostMySQL找出锁等待

MySQL找出锁等待

MySQL锁<一>

查询被锁住&执行慢

查询被锁住&执行慢

mysql数据库锁MDL锁的解释