一、什么是Table Metadata Lock
在MySQL以前的版本中,存在这样一个bug:
Description:
If user1 has an active transaction on a table and then user2 drops this table, then user1 does COMMIT, then in the binlog we have something like:
DROP TABLE t;
BEGIN;
INSERT INTO t … ;
COMMIT;
which is wrong.
MySQL官方文档链接:
http://bugs.mysql.com/bug.php?id=989
这个bug大致意思是说:当一个会话在主库执行DML操作还没提交时,另一个会话对同一个对象执行了DDL操作如drop table,而由于MySQL的binlog是基于事务提交的先后顺序进行记录的,因此在从库上应用时,就出现了先drop table,然后再向table中insert的情况,导致从库应用出错。
因此,MySQL在5.5.3版本后引入了Metadata lock,只有在事务结束后才会释放Metadata lock,因此在事务提交或回滚前,是无法进行DDL操作的。
MySQL官方文档位置:
http://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html
二、遇到的Metadata Lock问题
前几天时候,公司的开发同事让对一张表添加字段,由于该表数据量很大,因此使用了pt-online-change-schema工具进行字段的添加,在添加的过程中发现进度非常慢,通过shop processlist发现以及积累了大量的Metadata lock:Waiting for table metadata lock。
这些语句很明显是被添加字段的DDL所阻塞,但是DDL又是被谁阻塞了呢?
查询当前正在进行的事务:
mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 7202
trx_state: RUNNING
trx_started: 2016-07-20 23:02:53
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 52402
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 360
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: READ COMMITTED
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 10000
trx_is_read_only: 0
trx