昨天一同学说在slave上出现Waiting for table metadata lock,metadata lock在5.5版本新加的(http://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html)。metadata lock出现最多情况是一个事务中在t表进行DML时,另外一事务想对t表DDL,这时对t表DDL的事务只能等待,就会出现metadata,就是为了保护表的metadata。
出问题的备库上在跑mysqldump备份数据(参数有–single-transaction),一同学在主库drop table操作,导致备库一直hang住(备库延迟),show processlist就可以看到metadata lock。为什么mysqldump会对表加metadata lock的?
Mysqldump代码(5.5版本,5.1版本有点区别)
1、 if->flush tables成功,do->flush tables with read lock
2、 start transaction
3、 unlock tables
4、 backup(一个表一个表加metadata lock)
模拟mysqldump过程:
root@test >show TABLES;
+----------------+
| Tables_in_test |
+----------------+
| a |
| b |
| c |
+----------------+
Session 1:
root@test 06:46:20>flush TABLES WITH READ LOCK;
Query OK, 0 ROWS affected (0.00 sec)root@test 06:48:16>start TRANSACTION;
Query OK, 0 ROWS affected (0.00 sec)root@test 06:48:23>unlock TABLES;
Query OK, 0 ROWS affected (0.00 sec)root@test 06:48:38>select * FROM a;
Empty SET (0.00 sec)
Session 2:
root@test 06:45:25>drop TABLE a; hang …
session 3:
root@test 06:50:18>drop TABLE b;
Query OK, 0 ROWS affected (0.62 sec)
Session 1:
root@test 06:48:47>select * FROM b;
ERROR 1146 (42S02): TABLE 'test.b' doesn't exist
root@test 06:51:41>select * from c;
Empty set (0.00 sec)
Session 3:
root@test 06:51:03>drop TABLE c; hang…
从上面测试可以知道,mysqldump是备份到哪个表,锁到哪个表。这里有产生一个新的问题:
Session I:
Mysqldump未备份到b表
Session II:
写操作记录到binlog中
drop table b,实际在mysqldump备份集里是没有b表的
当恢复时,因为要apply 写b表的binlog,但备份集恢复后根本就没有b表,所以会报表找不到表,这个在我们线上环境已出现。
总结:因为5.1没有metadata lock,所以出现几率会更大,5.5已改进扫到哪里加锁到哪里。
转自:http://www.dbunix.com/?p=3217