MySQL在繁忙的数据库服务器上ANALYZE 表安全吗?

2023年 11月 15日 56.9k 0

有时,需要使用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也会受到影响。以下是一个您可能会在此处结束的示例场景:

<code style="text-align: left;">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)

一个长查询使ANALYZE等待,但另一个通常非常快的查询现在也在等待。

MySQL 8.0系列也可能出现同样的情况,包括8.0.23。幸运的是,在8.0.24版本中有一个修复程序可以解决这个问题。我们只能在发布说明中读到关于“取消等待”的一些克制的评论:

https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-24.html

事实上,从版本8.0.24开始,长时间运行的查询中的类似测试会导致即时查询执行:

<code >mysql > select @@version,@@version_comment;
+-----------+------------------------------+
| @@version | @@version_comment |
+-----------+------------------------------+
| 8.0.24 | MySQL Community Server - GPL |
+-----------+------------------------------+
1 row in set (0.00 sec)

mysql > analyze table sbtest1;
+-------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-------------+---------+----------+----------+
| db1.sbtest1 | analyze | status | OK |
+-------------+---------+----------+----------+
1 row in set (0.00 sec)

然而,我们仍然可以在官方文档中找到一个警告,即使是8.1版本,如下所示:

请求更新相关的错误报告以及相应的文档问题:

https://bugs.mysql.com/bug.php?id=87065

https://bugs.mysql.com/bug.php?id=112670

Percona Server for MySQL

如上所述,作为解决该错误报告的结果,Percona引入了一个修复并删除了不必要的表定义缓存锁:

https://jira.percona.com/browse/PS-2503

当使用Percona变体时,从版本5.6.38和5.7.20开始运行ANALYZE TABLE就已经是安全的了,因为这些版本是当时的活动开发系列。您可以在此处阅读发行说明中的公告:

https://docs.percona.com/percona-server/5.7/release-notes/Percona-Server-5.7.20-18.html#bugs-fixed

Percona Server for MySQL 5.7从第一个版本(我测试过,包括第一个GA版本8.0.13-3)开始就没有这个问题,因为改进是从Percona Server for MySQL 5.7系列合并而来的。

总结

MySQL 8.0.24+版本最新版本上,运行ANALYZE TABLE应该是绝对安全的,不会导致任何意外的停顿。5.7系列没有任何改进,这意味着即使是最新的5.7.43也可能会受到影响。

Percona MySQL系列的三个服务器(5.6.38+、5.7.20+和8.0.x)的用户都是安全的,不会导致任何意外的停顿。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论