5.5版本中mysqldump一些改进

昨天一同学说在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已改进扫到哪里加锁到哪里。

留下问题:
1、为什么不一次性把所有表加metalock,这样备份就一致了。
2、mysqldump的源码中2,3位置是否可换

下篇继续,写到这里,感谢希羽的分析


One Response to “5.5版本中mysqldump一些改进”

  1. hickey.liu@gmail.com说道:

    我对最后问题的理解:
    1. 从数据可服务性和dump出的数据一致上来做权衡,前者胜出。
    2. 不能,因为unlock tables之前是要得到一致的binlog file/pos.

Post a Comment