共计 3788 个字符,预计需要花费 10 分钟才能阅读完成。
自动写代码机器人,免费开通
这篇文章给大家分享的是有关 MySQL 数据库执行 analyze 采集信息的示例的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考。一起跟随丸趣 TV 小编过来看看吧。
故障简介
之前,有开发找到我,说应用的某个功能查询比以前慢了很多,让开发提供了慢的 SQL 语句,去对应的 MySQL 数据库看了一下执行计划,发现执行计划不正确,第一反应就是其中的一个表的统计信息不准确,导致了 SQL 语句的执行计划不对,从高效的查询 SQL 变成了慢 SQL。定位到问题之后,自然是 analyze 一下,重新采集信息,这个时候,却发现 analyze 表上的所有 select 突然卡住了,不返回任何结果,然后应用就炸了,各种告警短信。
故障复盘
当时执行 analyze 操作的是一个 slave 库,受影响基本是 select 查询,所以在这里模拟的是查询操作。
创建模拟表
mysql select * from t_test_1;
+----+--------+-------+--------+
| id | name | name2 | status |
+----+--------+-------+--------+
| 1 | name1 | 1001 | 0 |
| 2 | name1 | 1002 | 1 |
| 3 | name1 | 1003 | 1 |
| 4 | name1 | 1004 | 0 |
| 5 | name1 | 1005 | 1 |
| 6 | name1 | 1006 | 0 |
| 7 | name1 | 1007 | 2 |
| 8 | name1 | 1008 | 0 |
| 9 | name1 | 1009 | 1 |
| 10 | name10 | 1001 | 0 |
+----+--------+-------+--------+
10 rows in set (0.00 sec) 复制代码
模拟慢查询,由于这里数据量不够,所以用 sleep 代替
session1:模拟慢查询
mysql select sleep(1000) from t_test_1; 复制代码
session2:模拟收集表的统计信息
mysql analyze table t_test_1; 复制代码
session3:模拟执行 analyze 命令之后,在 t_test_1 表上执行一次 select 查询
mysql select * from t_test_1 where id=5; 复制代码
session4:查询所有会话信息
mysql select * from processlist order by time desc;
+----+------+-----------+--------------------+---------+------+-------------------------+----------------------------------------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+----+------+-----------+--------------------+---------+------+-------------------------+----------------------------------------------+
| 21 | root | localhost | testdb | Query | 242 | User sleep | select sleep(1000) from t_test_1 |
| 23 | root | localhost | testdb | Query | 180 | Waiting for table flush | analyze table t_test_1 |
| 24 | root | localhost | testdb | Query | 3 | Waiting for table flush | select * from t_test_1 where id=5 |
| 22 | root | localhost | information_schema | Query | 0 | executing | select * from processlist order by time desc |
+----+------+-----------+--------------------+---------+------+-------------------------+----------------------------------------------+
4 rows in set (0.00 sec) 复制代码
从 session4 获取的所有会话信息中,可以看到有 2 个会话的状态是“Waiting for table flush”。
Waiting for table flush 原因
当 MySQL 数据库做 FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, or OPTIMIZE TABLE 这些操作时,会导致需要关闭内存中的表,并重新打开表,加载新的表结构到内存中。但是关闭表,需要等待所有的在这个表上的操作执行结束(包括 select,insert,update,lock table 等),所以当有一个特别慢的 select 一直在执行时,analyze table 命令就一直无法结束。
解决方案
既然知道什么原因导致的 Waiting for table flush,就开始定位慢 sql 语句。在这里可以看到我们执行的是采集 t_test_1 表,所以需要查询涉及 t_test_1 表的慢查询,并且执行时间比 analyze table t_test_1 的执行时间还要长的会话。
mysql select * from processlist where info like %t_test_1% and time =(select time from processlist where id=23) order by time desc;
+----+------+-----------+--------+---------+------+-------------------------+----------------------------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+----+------+-----------+--------+---------+------+-------------------------+----------------------------------+
| 21 | root | localhost | testdb | Query | 1187 | User sleep | select sleep(1000) from t_test_1 |
| 23 | root | localhost | testdb | Query | 1125 | Waiting for table flush | analyze table t_test_1 |
+----+------+-----------+--------+---------+------+-------------------------+----------------------------------+
2 rows in set (0.37 sec) 复制代码
用上面的 sql 语句,很容易就定位到 id=21 的会话,导致 analyze table t_test_1 卡死,所以需要 kill 掉会话 21.
mysql kill 21;
Query OK, 0 rows affected (0.01 sec)
mysql show full processlist;
+----+------+-----------+--------------------+---------+------+----------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+--------------------+---------+------+----------+-----------------------+
| 22 | root | localhost | information_schema | Query | 0 | starting | show full processlist |
| 23 | root | localhost | testdb | Sleep | 1205 | | NULL |
| 24 | root | localhost | testdb | Sleep | 1028 | | NULL |
+----+------+-----------+--------------------+---------+------+----------+-----------------------+
3 rows in set (0.00 sec) 复制代码
杀掉会话,故障解除。
建议
生产执行 analyze table 建议
1. 执行之前,先估算一下表的数据量,根据经验预估需要消耗的时间,同时查看是否有采集信息表的慢 SQL,长事务在执行。
2. 避免在业务高峰期执行 analyze table 进行统计信息采集。
感谢各位的阅读!关于 MySQL 数据库执行 analyze 采集信息的示例就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到吧!
向 AI 问一下细节
丸趣 TV 网 – 提供最优质的资源集合!