mysql Waiting for table flush出现的原因及场景复现--LOCK TABLE READ

测试环境

centos7.6+mysql5.6.46

Waiting for table flush出现原因

官方文档:

https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html

The thread is executing FLUSH TABLES and is waiting for all threads to close their tables, or the thread got a notification that the underlying structure for a table has changed and it needs to reopen the table to get the new structure. However, to reopen the table, it must wait until all other threads have closed the table in question.

This notification takes place if another thread has used FLUSH TABLES or one of the following statements on the table in question: FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, or OPTIMIZE TABLE.

场景复现–LOCK TABLE READ

会话1
mysql> use yjgk;
mysql> select connection_id();
| 2 |
mysql> show tables;
| Tables_in_yjgk |
±---------------+
| aa |
| bb |
| t1 |
mysql> lock table bb read;

会话2
mysql> select connection_id();
| 3 |
mysql> flush table bb;
这里被hang住了
会话3
mysql> use yjgk
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
无法切换到yjgk数据y
[root@lineqi ~]# mysql -S /data/mysql_13306/mysql.sock -uroot -p -A
mysql> use yjgk;
Database changed
mysql> show tables;
±---------------+
| Tables_in_yjgk |
±---------------+
| aa |
| bb |
| t1 |
mysql> select * from t1;
±------±------±------------±-----------+
| fname | lname | region_code | dob |
±------±------±------------±-----------+
| aa | aa | 1 | 2020-08-12 |
| bb | bb | 65 | 2020-08-12 |
| cc | cc | 129 | 2020-08-12 |
±------±------±------------±-----------+

mysql> select * from bb;

mysql> show processlist;
+----+-----------------+-----------+------+------------+------+-------------------------+------------------+
| Id | User            | Host      | db   | Command    | Time | State                   | Info             |
+----+-----------------+-----------+------+------------+------+-------------------------+------------------+
|  1 | event_scheduler | localhost | NULL | Daemon     | 1699 | Waiting on empty queue  | NULL             |
|  2 | root            | localhost | yjgk | Sleep      | 1355 |                         | NULL             |
|  3 | root            | localhost | yjgk | Query      | 1340 | Waiting for table flush | flush table bb   |
|  4 | root            | localhost | yjgk | Field List | 1235 | Waiting for table flush |                  |
|  6 | root            | localhost | yjgk | Query      |  957 | Waiting for table flush | select * from bb |
|  7 | root            | localhost | yjgk | Query      |    0 | init                    | show processlist |
+----+-----------------+-----------+------+------------+------+-------------------------+------------------+

kill id=3的会话

mysql> flush table bb;
ERROR 2013 (HY000): Lost connection to MySQL server during query
再次查询发现id=4,6的状态还是Waiting for table flush

mysql> show full processlist;
+----+-----------------+-----------+------+------------+------+-------------------------+-----------------------+
| Id | User            | Host      | db   | Command    | Time | State                   | Info                  |
+----+-----------------+-----------+------+------------+------+-------------------------+-----------------------+
|  1 | event_scheduler | localhost | NULL | Daemon     | 6173 | Waiting on empty queue  | NULL                  |
|  2 | root            | localhost | yjgk | Sleep      | 1751 |                         | NULL                  |
|  4 | root            | localhost | yjgk | Field List | 5709 | Waiting for table flush |                       |
|  6 | root            | localhost | yjgk | Query      | 5431 | Waiting for table flush | select * from bb      |
|  7 | root            | localhost | yjgk | Query      |    0 | init                    | show full processlist |
+----+-----------------+-----------+------+------------+------+-------------------------+-----------------------+

查看哪个表还是在访问的语句
mysql> show open tables where In_use>=1;
±---------±------±-------±------------+
| Database | Table | In_use | Name_locked |
±---------±------±-------±------------+
| yjgk | bb | 1 | 0 |
±---------±------±-------±------------+

mysql> kill 2 ;
Query OK, 0 rows affected (0.00 sec)
kill掉ID=2的ID,结果正常了

mysql> show full processlist;
+----+-----------------+-----------+------+---------+------+------------------------+-----------------------+
| Id | User            | Host      | db   | Command | Time | State                  | Info                  |
+----+-----------------+-----------+------+---------+------+------------------------+-----------------------+
|  1 | event_scheduler | localhost | NULL | Daemon  | 6472 | Waiting on empty queue | NULL                  |
|  4 | root            | localhost | yjgk | Sleep   |   18 |                        | NULL                  |
|  6 | root            | localhost | yjgk | Sleep   | 5730 |                        | NULL                  |
|  7 | root            | localhost | yjgk | Query   |    0 | init                   | show full processlist |
|  8 | root            | localhost | yjgk | Sleep   |    9 |                        | NULL                  |
+----+-----------------+-----------+------+---------+------+------------------------+-----------------------+

但上面这个场景和我在生产环境遇到的情况还有所不同,这里是因为ID=2的会话命令为sleep,生产环境是sending data,是慢查询导致的。

总结

1、通过show open tables where in_use >=1;能找到是那张表被lock住了,但是无法定位到具体的线程,有没有相应的工具来实现呢
2、kill掉会话3时并不是解决waiting for table flush问题,需要找到罪魁祸首SQL对应的会话,即ID=2的,这一点与生产环境遇到的情况是一致的。
3、

猜你喜欢

转载自blog.csdn.net/weixin_41561946/article/details/108418632
今日推荐