MySQL在繁忙的数据库服务器上ANALYZE 表安全吗?
有时,需要使用ANALYZE table命令手动更新表和索引统计信息。在不深入讨论这种需求的原因的情况下,我想从与在生产系统上运行该命令相关的开销方面刷新这个主题。然而,这里讨论的开销与深入表行收集统计信息的通常成本无关,我们可以通过设置示例页面的数量来控制统计信息。
五年前,Percona Server for MySQL中引入的一项改进,以解决与运行命令相关的不必要的停顿:
https://www.percona.com/blog/analyze-table-is-no-longer-a-blocking-operation/
从历史上看,在MySQL中运行ANALYZE TABLE命令的问题是查询需要对表的表定义缓存项进行独占锁定。这使得查询等待任何长时间运行的查询完成,但也可能触发级联等待其他传入请求。简而言之,ANALYZE可能会在繁忙的生产环境中导致严重的停机。
从那时起,情况发生了很大变化,但今天仍有许多生产系统运行受影响的版本。让我们回顾一下这些年来情况是如何演变的。
MySQL Server – Community Edition
该问题适用于8.0.23之前的所有上游MySQL社区版本。5.7系列没有任何改进(顺便说一句,十月将达到EOL!),这意味着即使是最新的5.7.43也会受到影响。以下是一个您可能会在此处结束的示例场景:
mysql > select @@version,@@version_comment;
+-----------+------------------------------+
| @@version | @@version_comment |
+-----------+------------------------------+
| 5.7.43 | MySQL Community Server (GPL) |
+-----------+------------------------------+
1 row in set (0.00 sec)
mysql > show processlist;
+----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+
| 4 | msandbox | localhost | db1 | Query | 54 | Sending data | select avg(k) from sbtest1 where pad not like '%f%' group by c |
| 13 | msandbox | localhost | db1 | Query | 29 | Waiting for table flush | analyze table sbtest1 |
| 17 | msandbox | localhost | db1 | Query | 0 | starting | show processlist |
| 18 | msandbox | localhost | db1 | Query | 15 | Waiting for table flush | select * from sbtest1 where id=100 |
+----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+
4 rows in set (0.00 sec)