MySQL 与主流分支版本上执行 ANALYZE TABLE 安全么?
有时,需要使用 ANALYZE TABLE 命令手动更新表和索引统计信息。在不进一步探讨这种需求的原因的情况下,我想就与在生产系统上运行命令相关的开销来聊聊这个话题。然而,这里讨论的开销与深入表行收集统计信息的通常成本无关,我们可以通过设置样本页数 来控制。
五年前,我的同事 Sveta 发布了一篇不错的博客文章,介绍了 Percona Server for MySQL 中引入的一项改进,以解一些不必要的等待:
从历史上看,在 MySQL 中运行 ANALYZE TABLE 命令的问题是查询需要在表的表定义缓存条目上使用排他锁。这使得查询等待任何长时间运行的查询完成,但也可能触发级联等待其他传入请求。简而言之,ANALYZE 可能会导致高负载生产环境中出现较高得延时。
从那时起,MySQL/Percona/MariaDB 都发生了一些变化,但今天仍然存在许多生产系统会受影响的版本。让我们回顾一下这些年来情况的演变。
MySQL
该问题适用于 MySQL 8.0.23 之前的所有版本。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)
一个慢查询导致 ANALYZE 在等待,且另一个通常非常快的查询现在也在等待。
同样的情况也可能发生在 MySQL 8.0 系列,包括 8.0.23。幸运的是,8.0.24 版本中修复了这个问题。我们只能在发行说明 中读到一些关于此问题解决得评论:
事实上,从版本 8.0.24 开始,运行慢查询期间的类似测试会导致即时查询执行:
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 版本,我们仍然可以在官方文档中找到警告,如下所示:
ANALYZE TABLE removes the table from the table definition cache, which requires a flush lock. If there are long running statements or transactions still using the table, subsequent statements and transactions must wait for those operations to finish before the flush lock is released. Because ANALYZE TABLE itself typically finishes quickly, it may not be apparent that delayed transactions or statements involving the same table are due to the remaining flush lock.
Percona
如上所述,为了解决此错误报告,Percona 引入了修复程序并删除了不必要的表定义缓存锁。
使用 Percona 时,从版本 5.6.38 和 5.7.20 开始运行 ANALYZE TABLE 已经是安全的,因为这些是当时活跃的版本。
自第一个版本(包括第一个 GA 版本 8.0.13-3 )以来,Percona Server for MySQL 版本 8.0 就没有这个问题,因为改进是从 Percona Server for MySQL 5.7 系列合并而来的。
MariaDB
ANALYZE TABLE 的问题发生于 10.5.3 之前的所有 MariaDB 版本。在版本 10.5.4 中,Percona 得以解决。
因此,当您在 10.5.3 或更低版本以及任何以前的系列(甚至是最新的 10.4.31)中运行查询时,可能会出现类似的情况:
mysql > select @@version,@@version_comment; +----------------+-------------------+ | @@version | @@version_comment | +----------------+-------------------+ | 10.5.3-MariaDB | MariaDB Server | +----------------+-------------------+ 1 row in set (0.000 sec) mysql > show processlist; +----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+----------+ | Id | User | Host | db | Command | Time | State | Info | Progress | +----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+----------+ | 4 | msandbox | localhost | db1 | Query | 18 | Sending data | select avg(k) from sbtest1 where pad not like '%f%' group by c | 0.000 | | 13 | msandbox | localhost | db1 | Query | 16 | Waiting for table flush | analyze table sbtest1 | 0.000 | | 14 | msandbox | localhost | db1 | Query | 14 | Waiting for table flush | select * from sbtest1 where id=100 | 0.000 | | 15 | msandbox | localhost | NULL | Query | 0 | starting | show processlist | 0.000 | +----+----------+-----------+------+---------+------+-------------------------+----------------------------------------------------------------+----------+ 4 rows in set (0.000 sec) mysql > select @@version,@@version_comment; +-----------------+-------------------+ | @@version | @@version_comment | +-----------------+-------------------+ | 10.4.31-MariaDB | MariaDB Server | +-----------------+-------------------+ 1 row in set (0.000 sec) mysql > show processlist; +----+-------------+-----------+------+---------+------+--------------------------+----------------------------------------------------------------+----------+ | Id | User | Host | db | Command | Time | State | Info | Progress | +----+-------------+-----------+------+---------+------+--------------------------+----------------------------------------------------------------+----------+ | 1 | system user | | NULL | Daemon | NULL | InnoDB purge coordinator | NULL | 0.000 | | 2 | system user | | NULL | Daemon | NULL | InnoDB purge worker | NULL | 0.000 | | 3 | system user | | NULL | Daemon | NULL | InnoDB purge worker | NULL | 0.000 | | 4 | system user | | NULL | Daemon | NULL | InnoDB purge worker | NULL | 0.000 | | 5 | system user | | NULL | Daemon | NULL | InnoDB shutdown handler | NULL | 0.000 | | 9 | msandbox | localhost | db1 | Query | 18 | Sending data | select avg(k) from sbtest1 where pad not like '%f%' group by c | 0.000 | | 18 | msandbox | localhost | db1 | Query | 16 | Waiting for table flush | analyze table sbtest1 | 0.000 | | 19 | msandbox | localhost | db1 | Query | 12 | Waiting for table flush | select * from sbtest1 where id=100 | 0.000 | | 22 | msandbox | localhost | NULL | Query | 0 | Init | show processlist | 0.000 | +----+-------------+-----------+------+---------+------+--------------------------+----------------------------------------------------------------+----------+ 9 rows in set (0.000 sec)
总结
只要您的数据库在最新版本的 MySQL 或 MariaDB 上运行,运行 ANALYZE TABLE 就应该绝对安全,不会导致任何意外的停顿。
Percona Server for MySQL 系列:5.6.38+、5.7.20+ 和 8.0.x 的用户都是安全的。
MariaDB 用户必须升级到 10.5.4 或更高版本以避免锁定问题。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
SQLE 获取
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一则 MongoDB 副本集迁移实操案例
文中详细阐述了通过全量 + 增量 Oplog 的迁移方式,完成一套副本集 MongoDB 迁移的全过程。 作者:张然,DBA 数据库技术爱好者~ 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。 本文约 900 字,预计阅读需要 3 分钟。 背景介绍 客户要将生产环境上一套副本集架构的 MongoDB 进行迁移,数据量 240GB 左右。经过测试,全量备份耗时 3.5 小时,恢复耗时 4.5小时。 为了减少割接时间,采取全量 + 增量 Oplog 的迁移方式。提前一天进行全备,割接当天只需备份增量的 Oplog 恢复即可,可大幅减少割接窗口。 实操过程 查看 Oplog 信息 检查并评估生产环境 Oplog 的产生信息,以防全量和增量备份期间产生的 Oplog 被覆盖掉。 mongo> db.getReplicationInfo() { "logSizeMB" : 20480, "usedMB" : 20374.38, "timeDiff" : 7074665, "timeDiffHours" : 1965.18, "tFirst" : "Fri Fe...
- 下一篇
基于 eBPF 构建下一代智能可观测系统
本文基于 KubeCon China 2023 分享整理我们今天分享的主题是基于 eBPF 构建下一代智能可观测系统。 在开始之前呢,我先介绍一下我们自己。我是刘恺,花名是千陆,目前是阿里云 ARMS K8s 监控子产品的负责人。这位是我的同事董善东博士,花名梵登,他是阿里云 ARMS 产品 AIOps 领域的负责人。 K8s 中的可观测挑战 本次的分享主要分为三部分内容。我们先来看第一部分,K8s 中的可观测挑战。 随着云原生、K8s、微服务等概念的兴起,我们的应用发生了很多变化,比如微服务化、容器化等等。那么一切都朝着统一的标准发展,这就带给我们非常多的好处。比如极致的弹性、高效的运维、标准的运行时环境等等。但同时,K8s 也为开发者带来了很多的问题。 我们在公有云上收集了 1000 多个 K8s 中的工单,开发者将自己的基础架构迁移到 K8s 之后,实际都遇到了哪些问题呢? 通过分析工单,我们可以分析出三大挑战: 第一个,K8s 基础设施问题不容乐观,从统计图中可以看到网络相关的问题占比在 56% 以上,那么开发者在遇到这些问题的时候,作为可观测系统,我们需要采集什么数据才能回答...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS6,7,8上安装Nginx,支持https2.0的开启