可通过执行SHOW VARIABLES LIKE 'slow_query_log'、'long_query_log_file'、'long_query_time'三条命令确认MySQL慢查询日志是否启用及阈值;默认通常为OFF且long_query_time=10秒,需手动设为ON并调低阈值(如0.5秒)以适配线上需求。

如何确认 MySQL 当前慢查询阈值和日志是否启用
MySQL 的慢查询监控依赖两个核心配置:是否开启慢查询日志,以及 long_query_time 设为多少。默认多数发行版(如 Percona、官方二进制包)不启用慢查询日志,且 long_query_time 默认是 10 秒——这对线上服务几乎没意义。
执行以下命令直接检查:
SHOW VARIABLES LIKE 'slow_query_log';<br>SHOW VARIABLES LIKE 'long_query_log_file';<br>SHOW VARIABLES LIKE 'long_query_time';
常见错误现象:slow_query_log 显示 OFF;或 long_query_time 是 10,但业务里 500ms 就卡顿。别信“默认已开”,必须手动确认并修改。
- 用
SET GLOBAL slow_query_log = ON可临时开启,但重启失效;要持久化,得写进my.cnf的[mysqld]段落 -
long_query_time支持小数,例如设为0.5表示记录超过 500ms 的查询(注意:单位是秒,不是毫秒) - MySQL 5.7+ 支持按微秒精度统计(需开启
log_queries_not_using_indexes配合),但阈值仍以秒为单位
为什么不能只靠 slow_query_log 文件做峰值告警
慢查询日志是追加写入的文本文件,没有结构化时间戳字段(只有日志行开头的日期,格式还随系统 locale 变),无法直接用 tail -f + awk 精确统计“每分钟新增慢查询数”。更关键的是:日志写入有延迟,且可能被并发刷盘截断,导致漏计或重复计。
真实监控场景下,你关心的是“过去 5 分钟内慢查询突增到 200 条/分钟”,而不是“今天总共写了 1289 行日志”。所以必须绕过日志文件,改用性能模式(Performance Schema)或信息模式(INFORMATION_SCHEMA)中的实时指标。
- MySQL 5.6+ 推荐查
performance_schema.events_statements_summary_by_digest,它聚合了 SQL 模板级的执行统计,含avg_timer_wait和sum_timer_wait,可反推慢查询比例 - MySQL 8.0+ 可结合
sys.schema_table_statistics_with_buffer视图快速定位高延迟表,但不直接反映“峰值” - 避免用
SHOW PROCESSLIST抓当前慢查询——它只反映瞬时状态,错过就没了,无法支撑趋势告警
用 pt-query-digest 实时解析慢日志并输出峰值速率
Percona Toolkit 的 pt-query-digest 是目前最靠谱的慢日志分析工具,它能边读日志边统计单位时间内的查询频次,支持 --review-history 写入数据库做趋势对比,也支持 --report-format=profile 输出带时间窗口的汇总。
典型用法(假设慢日志路径是 /var/lib/mysql/slow.log):
pt-query-digest --since '2024-04-01 14:00:00' --until '2024-04-01 14:05:00' /var/lib/mysql/slow.log
但要注意:它本身不提供“持续流式告警”,必须配合定时任务或管道触发。容易踩的坑:
- 日志轮转后路径变了(比如变成
slow.log.1.gz),pt-query-digest不会自动解压或跳转,需用zcat或gunzip -c预处理 - 默认只分析 query digest,不区分客户端 IP 或用户,若需按应用拆分,得加
--filter '$event->{user} =~ m/^app_/i' - 输出里的 “Rank” 列是按总响应时间排序,不是按出现频次;要看“Queries ranked by number of times executed”,得加
--report-format=Query_review
在 Prometheus + Grafana 中构建慢查询速率告警
如果已有 Prometheus,推荐用 mysqld_exporter 暴露指标,其中 mysql_global_status_slow_queries 是累计值(类似 uptime),不是速率。真正可用的是它的衍生指标:rate(mysql_global_status_slow_queries[5m]),即每秒新增慢查询数。
这个值乘以 60 就是“每分钟慢查询数”,可设告警阈值(例如 > 30/min)。但要注意兼容性细节:
- MySQL 5.7 之前该指标更新不及时(可能滞缓几十秒),建议升级到 5.7.11+ 或 8.0.22+
-
mysqld_exporter默认不采集 performance_schema 表,若想监控更细粒度(如某类 SQL 的慢查率),需额外配置--collect.perf_schema.eventswaits - 告警规则里别直接用
rate(...[5m])做条件判断,应改用increase(...[5m])防止因抓取间隔抖动误报
复杂点在于:慢查询峰值往往是局部的、短时的(比如 30 秒内冲到 200 条),而 Prometheus 抓取间隔通常是 15–30 秒。这意味着你看到的“峰值”其实是平滑后的结果,真实毛刺可能被抹平。真要捕获亚秒级脉冲,得上 pt-query-digest --watch-server 配合本地 socket 监听,或者改用 eBPF 工具(如 mysqld-bpfcc),但那已是另一个层级的投入了。


















