MySQL慢查询持续采集,Prometheus监控慢查询数量
MySQL 慢查询是数据库性能问题最常见的信号之一。
如果等到用户投诉才去排查,往往已经影响线上业务。
本文会带你从零开始,用 Prometheus 和 mysqld_exporter 持续采集 MySQL 慢查询数量,并在慢查询指标异常增长时触发告警。
整个过程不依赖付费监控平台,适合自己掌握服务器和数据库的运维人员操作。
准备工作:需要哪些环境和权限
开始之前,确认以下几项已经就绪:
- 一台能联网的 Linux 服务器,已装好 MySQL 5.7 或 8.x。
- MySQL 有至少一个账号,拥有
PROCESS、REPLICATION CLIENT和SELECT权限(用于 exporter 读取状态变量)。 - 服务器可以访问
prometheus.io下载安装包,或者你已有离线安装包。 - 熟悉基本 Linux 命令,比如
vim、systemctl。
先检查 MySQL 当前是否开启了慢查询日志。
执行:
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
如果 slow_query_log 是 OFF,需要开启。
可以临时开启,也可以写入配置文件永久生效:
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
修改后重启 MySQL,
或者执行 SET GLOBAL slow_query_log = 'ON'; 热开启。long_query_time 建议从 1 秒开始,
后续再根据业务调整。
部署 mysqld_exporter:把慢查询指标暴露出来
mysqld_exporter 是 Prometheus 官方提供的 MySQL 指标采集器,它会连接 MySQL 读取 SHOW GLOBAL STATUS 等性能数据。
下载并解压(以 Linux amd64 为例,版本号请以官方最新 release 为准):
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.1/mysqld_exporter-0.15.1.linux-amd64.tar.gz
tar -xzf mysqld_exporter-0.15.1.linux-amd64.tar.gz
sudo mv mysqld_exporter-0.15.1.linux-amd64 /usr/local/mysqld_exporter
创建 MySQL 专用监控账号(建议不要用 root):
CREATE USER 'exporter'@'localhost' IDENTIFIED BY '你的强密码';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
FLUSH PRIVILEGES;
然后创建 exporter 配置文件,保存数据库连接信息:
sudo mkdir -p /etc/mysqld_exporter
sudo vim /etc/mysqld_exporter/.my.cnf
写入内容:
[client]
user=exporter
password=你的强密码
启动 exporter 时指定配置文件:
/usr/local/mysqld_exporter/mysqld_exporter --config.my-cnf=/etc/mysqld_exporter/.my.cnf --web.listen-address=:9104
确认 exporter 正常运行,访问 http://服务器IP:9104/metrics,能看到输出一大段指标文本。
重点关注下面两个和慢查询相关的指标:
mysql_global_status_slow_queries:累计慢查询次数。mysql_global_variables_long_query_time:慢查询阈值(秒)。
配置 Prometheus:持续抓取慢查询指标
如果你还没有 Prometheus,先下载并启动:
wget https://github.com/prometheus/prometheus/releases/download/v2.53.0/prometheus-2.53.0.linux-amd64.tar.gz
tar -xzf prometheus-2.53.0.linux-amd64.tar.gz
cd prometheus-2.53.0.linux-amd64
编辑 prometheus.yml,在 scrape_configs 下添加 MySQL 采集任务:
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['localhost:9104']
如果你的 Prometheus 和 MySQL 不在同一台机器,把 localhost 换成 exporter 所在服务器的 IP。
启动 Prometheus:
./prometheus --config.file=prometheus.yml
验证是否采集成功:
打开 Prometheus 的 Web 界面(默认端口 9090),
在查询框输入 mysql_global_status_slow_queries,
点 Execute,
如果出现数值和时序图,
说明 MySQL 慢查询指标已经持续采集到了。
设置慢查询数量告警:使用 Prometheus 内置规则
不装 Alertmanager,Prometheus 也可以在 Web 界面看到告警状态,但不会主动通知你。
先讲最直接的规则配置,再补充 Alertmanager 通知。
在 Prometheus 同目录下新建规则文件 slow_query_rules.yml:
groups:
- name: mysql_slow_query
rules:
- alert: MySQLSlowQueriesHigh
expr: increase(mysql_global_status_slow_queries[5m]) > 50
for: 2m
labels:
severity: warning
annotations:
summary: "MySQL 慢查询异常增长"
description: "最近5分钟内新增慢查询数量超过50次,当前值:{{ $value }}"
然后在 prometheus.yml 中加载这个规则文件:
rule_files:
- "slow_query_rules.yml"
重启 Prometheus,让规则生效:
# 先检查配置是否正常
./promtool check config prometheus.yml
# 重启后,在 Web 界面 Alerts 页面查看规则状态
触发条件说明:increase(mysql_global_status_slow_queries[5m]) 计算的是 5 分钟内慢查询计数的增量。
如果增量超过 50 并持续 2 分钟,就会触发告警。
这个阈值请根据你业务实际情况调整,比如有些系统 5 分钟 10 条就已经很严重了。
接入 Alertmanager:让告警真正通知到你
上面只是把告警状态展示在 Prometheus 界面,真正要收到通知,需要部署 Alertmanager。
下载并解压 Alertmanager(版本以官方发布为准):
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar -xzf alertmanager-0.27.0.linux-amd64.tar.gz
编辑 alertmanager.yml,配置一个最简单的 Webhook 或邮件通知。
以钉钉/企业微信 Webhook 为例,把 URL 换成你自己的机器人类:
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 2m
repeat_interval: 30m
receiver: 'webhook'
receivers:
- name: 'webhook'
webhook_configs:
- url: 'https://oapi.dingtalk.com/robot/send?access_token=你的token'
send_resolved: true
然后启动 Alertmanager(默认端口 9093):
./alertmanager --config.file=alertmanager.yml
最后在 Prometheus 配置中关联 Alertmanager:
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
重启 Prometheus。
当慢查询规则触发后,Alertmanager 会按配置把告警消息推送到你的钉钉群。别忘了测试 Webhook 地址是否真实可用,很多告警发不出去都是因为 token 填错或机器人权限没开。
避坑指南:新手最容易踩的四个坑
第一,exporter 账号密码泄露风险。 .my.cnf 文件要限制权限:
chown root:root /etc/mysqld_exporter/.my.cnf
chmod 600 /etc/mysqld_exporter/.my.cnf
第二,慢查询日志只统计 SQL 执行时间,不统计锁等待时间。 一些复杂查询可能实际很慢,但因为锁等待被排除在外。
如果需要关注锁等待,建议额外监控 performance_schema 相关指标。
第三,increase() 在计数器重启后会误判。 如果 Prometheus 或 MySQL 重启,计数归零,increase() 可能计算出很大的值。
建议加上 for: 2m 等待持续触发,减少瞬时误报。
第四,
监控账号权限不足。 如果 exporter 启动后看不到 mysql_global_status_slow_queries,
先检查账号权限是否给了 PROCESS,
没有该权限时 MySQL 会拒绝部分全局状态读取。
验证效果:确认慢查询采集和告警链路都正常
完成配置后,按下面的步骤验证:
- 在 MySQL 里手动执行一条耗时超过
long_query_time的 SQL:
SELECT SLEEP(2);
- 在 Prometheus 查询页面执行
increase(mysql_global_status_slow_queries[2m]),能看到数值增加。 - 连续执行几次
SELECT SLEEP(2);,触发告警条件,检查 Prometheus 的 Alerts 页面是否变为Pending,然后变成Firing。 - 确认钉钉或其他通知渠道是否收到告警内容。
如果 5 分钟后还没收到通知,依次检查:Alertmanager 是否运行、Webhook 地址是否正确、Prometheus 配置里 alerting 是否指向正确的 Alertmanager 地址。
也可以直接在 Alertmanager 的 Web 界面 /#/alerts 查看是否收到告警。
MySQL 慢查询监控不是为了惩罚慢 SQL,而是为了尽早发现性能拐点。
建议监控持续稳定运行两周后,回头分析慢查询数量基线,再调整告警阈值。
这样既能避免漏报,也不会被不重要的慢查询提醒骚扰。
如果后续需要把慢查询明细也放进去看,可以考虑结合 mysqld_exporter 的 log_slow_filter 或者收集慢查询日志到 Loki,那是另一套方案了。