前几日操作truncate table
操作时,遇到一个问题,通过show processlist
获取关键信息,通过此文章了解更多,故记录于此。
什么是Table Metadata Lock
在MySQL以前的版本中,存在这样一个Bug:
大致意思如下:
如果user1存在一个操作table的事务,而user2要删除这张表,当user1提交这个事务时,binlog表现出来的行为类似如下:
1 | DROP TABLE t; |
这样就导致这个问题出现了。
所以MySQL在后续版本中增加了Metadata Lock,只有在事务结束后才会释放Metadata lock,因此在事务提交或回滚前,是无法进行DDL(不仅仅是DDL哦)操作的。
MySQL官方文档地址:
http://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html
如何解决
查询当前正在运行的事务(下面为拷贝过来的,仅作参考)
1 | mysql> select * from information_schema.innodb_trx\G |
查看运行的SQL语句
根据查询到的trx_started时间以及trx_mysql_thread_id到MySQL的general log中查找,当然前提是开启了general log的功能,对于这句话我有一个疑惑点,如果没有开启general log时那么无法查看对应操作的SQL语句了???
所以此处给出排查方式:
- 如果开启了general log,那么根据这个方式
- 给出两个SQL语句如下,参考文章:
1 | -- 这条语句用于查看哪个线程被另外哪一个线程阻塞, 分别为 阻塞的线程ID、阻塞的SQL的语句、谁阻塞的、阻塞者的SQL语句 |
但是方式2不一定能够打印出具体阻塞的语句,为什么,如果出现此类问题,可以先看下autocommit,哈哈…
如果还是无法定位SQL,那么还是暴力一点:
1 | mysql> kill 52402; |
如何复现这种情况(另外对于主主/主从复制也会出现),可参考文章