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的锁等待队列。若是是产品环境的核心表出现了这样的锁等待队列,就会形成灾难性的后果。html
形成alter table产生Waiting for table metadata lock的缘由其实很简单,通常是如下几个简单的场景:mysql
经过show processlist
能够看到TableA上有正在进行的操做(包括读),此时alter table语句没法获取到metadata 独占锁,会进行等待。sql
这是最基本的一种情形,这个和mysql 5.6中的online ddl并不冲突。通常alter table的操做过程当中(见下图),在after create步骤会获取metadata 独占锁,当进行到altering table的过程时(一般是最花时间的步骤),对该表的读写均可以正常进行,这就是online ddl的表现,并不会像以前在整个alter table过程当中阻塞写入。(固然,也并非全部类型的alter操做都能online的,具体能够参见官方手册:http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html)
处理方法: kill 掉 DDL所在的session.session
经过show processlist看不到TableA上有任何操做,但实际上存在有未提交的事务,能够在 information_schema.innodb_trx中查看到。在事务没有完成以前,TableA上的锁不会释放,alter table一样获取不到metadata的独占锁。ui
处理方法:经过select * from information_schema.innodb_trx\G
, 找到未提交事物的sid, 而后 kill 掉,让其回滚。日志
这极可能是由于在一个显式的事务中,对TableA进行了一个失败的操做(好比查询了一个不存在的字段),这时事务没有开始,可是失败语句获取到的锁依然有效,没有释放。从performance_schema.events_statements_current表中能够查到失败的语句。code
官方手册上对此的说明以下:orm
If the server acquires metadata locks for a statement that is syntactically valid but fails during execution, it does not release the locks early. Lock release is still deferred to the end of the transaction because the failed statement is written to the binary log and the locks protect log consistency.server
也就是说除了语法错误,其余错误语句获取到的锁在这个事务提交或回滚以前,仍然不会释放掉。because the failed statement is written to the binary log and the locks protect log consistency 可是解释这一行为的缘由很难理解,由于错误的语句根本不会被记录到二进制日志。htm
处理方法:经过 select * from performance_schema.events_statements_current
找到其sid, kill 掉该session. 也能够 kill 掉DDL所在的session.
总之,alter table的语句是很危险的(其实他的危险实际上是未提交事物或者长事务致使的),在操做以前最好确认对要操做的表没有任何进行中的操做、没有未提交事务、也没有显式事务中的报错语句。若是有alter table的维护任务,在无人监管的时候运行,最好经过lock_wait_timeout设置好超时时间,避免长时间的metedata锁等待。
本文转自https://www.cnblogs.com/digdeep/p/4892953.html