MySQL DDL中碰到Waiting for table metadata lock

Waiting for table metadata lock

在进行线上表操作的时候,线上的CPU和IOPS等均不非常低,但是对一张表进行DDL(drop|truncate|rename|repair)均没有任何反应,在processlist中,会看到报Waiting for table metadata lock


  • MySQL官方手册对WFTML中的解释(片段摘录)
MySQL uses metadata locking to manage concurrent access to database objects and to ensure data consistency. Metadata locking applies not just to tables, but also to schemas and stored programs (procedures, functions, triggers, and scheduled events)
To ensure transaction serializability, the server must not permit one session to perform a data definition language (DDL) statement on a table that is used in an uncompleted explicitly or implicitly started transaction in another session. The server achieves this by acquiring metadata locks on tables used within a transaction and deferring release of those locks until the transaction ends. A metadata lock on a table prevents changes to the table's structure. This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends.

而我碰到的问题,其实更奇葩,为什么?因为我所要处理的表是另外一张表,我定义为A表,而有个长事务影响的事B表,两张表并没有直接关联,也没有外键关系,非常独立。但是对A表进行DDL,就会产生这个MDL锁


对事务的查询

SELECT * FROM information_schema.innodb_trx;

MySQL DDL中碰到Waiting for table metadata lock_第1张图片
可以看到,有一个超长事务在跑(距离故障已经有5个小时以上),其实这是个bug程序,但因为取的数据较少,从几百万中的表中分50条一次,循环跑,所以事务一直存在,实际上是有问题的。由于这个事务无关痛痒,直接kill掉
需要注意

  • 确定对应的pid,也就是对应的trx_mysql_thread_id才对
  • 在processlist中确定这条SQL是由那个账号产生的,使用该账号将其kill(没有super特权账号情况下)

MySQL DDL中碰到Waiting for table metadata lock_第2张图片

总结

在这个故障案例中,其实并不是同一个表,而官网说针对的MDL锁,实际上是同一个表才会产生这种情况,而故障情况来看,大胆推测应该上升到了库的元数据级别的锁,也就是官网手册中的第一句话

MySQL uses metadata locking to manage concurrent access to database objects and to ensure data consistency. Metadata locking applies not just to tables, ***but also to schemas and stored programs*** (procedures, functions, triggers, and scheduled events)

but also to schemas and stored programs:从这句话反推应该是导致了这个故障的最根本原因,库级别的MDL锁。
大致解决的思路

  1. 查找是否有超长事务
  2. 确定事务是否有所关联的库及账号
  3. 登录对应的账号使用kill干掉即可

你可能感兴趣的:(MySQL,mysql,medadata,MDL)