MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列。如果是生产环境的核心表出现了这样的锁等待队列,就会造成灾难性的后果,比如电商中的订单表。
遇到该种情况的解决方法:
1、show processlist
通过show processlist可以看到TableA上有正在进行的操作(包括读),此时alter table语句无法获取到metadata 独占锁,会进行等待。找到sid, 对应字段为id,直接kill
2、select * from information_schema.innodb_trx\G
通过select * from information_schema.innodb_trx\G
找到未提交的事务的sid, 对应字段为trx_mysql_thread_id, 直接kill
3、select * from performance_schema.events_statements_current;
通过show processlist看不到TableA上有任何操作,在information_schema.innodb_trx中也没有任何进行中的事务。这很可能是因为在一个显式的事务中,对TableA进行了一个失败的操作(比如查询了一个不存在的字段),这时事务没有开始,但是失败语句获取到的锁依然有效,没有释放。从performance_schema.events_statements_current表中可以查到失败的语句。
找到sid,对应字段为thread_id, 直接kill
4、lock_wait_timeout
最好的方式是设置过期时间,避免长时间metadata 锁等待