生产环境MySQL变慢怎么办Prometheus Grafana Zabbix主流监控工具实战对比与选型建议
一、那个深夜报警炸裂的下午
凌晨三点,产品经理的电话直接把老王从床上拽了起来。”线上数据库响应时间飙升到2秒以上,用户投诉如潮!”
老王揉了揉惺忪的睡眼,打开终端,开始了一连串的排查操作:
SHOW PROCESSLIST;看到几十个卡在Sending data状态的连接SHOW ENGINE INNODB STATUS;发现大量的buffer pool等待SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%';行锁竞争严重
半小时后,老王终于定位到问题——一个没有走索引的大表扫描查询,被某个新上线的活动功能触发,直接拖垮了整个MySQL实例。
“如果我有更完善的监控体系,至少能在性能下降到可感知之前收到告警。” 老王事后反思。
这个故事真实吗?太真实了。几乎所有DBA和技术负责人都经历过类似的”救火”时刻。今天,我们就来聊聊如何让MySQL监控不再”亡羊补牢”。
二、MySQL慢在哪里?先读懂它的语言
在讨论监控工具之前,我们必须先搞清楚:MySQL变慢时,它会在哪些方面”示警”?
2.1 CPU瓶颈
-- 查看CPU相关状态
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
-- 通过information_schema查询当前慢查询
SELECT * FROM information_schema.processlist
WHERE COMMAND != 'Sleep'
ORDER BY TIME DESC
LIMIT 10;
CPU飙升时,你通常会看到:
Threads_running持续处于高位- 大量复杂的聚合查询或排序操作
- 频繁的全表扫描
2.2 内存压力
-- InnoDB Buffer Pool使用情况
SHOW ENGINE INNODB STATUS\G
-- 关键指标
-- Innodb_buffer_pool_read_requests -- 逻辑读
-- Innodb_buffer_pool_reads -- 物理读
-- 比值应该接近1,物理读越少越好
当Buffer Pool命中率低于95%时,就需要警惕了。
2.3 磁盘I/O
-- 检查磁盘队列长度
SHOW GLOBAL STATUS LIKE 'Innodb_data_reads';
SHOW GLOBAL STATUS LIKE 'Innodb_data_writes';
-- 结合操作系统命令
iostat -x 1 10
2.4 连接数爆炸
-- 查看连接配置
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'wait_timeout';
-- 当前连接分布
SELECT
SUBSTRING_INDEX(host, ':', 1) AS host,
COUNT(*) AS connections,
SUM(IF(command = 'Sleep', 1, 0)) AS sleep_count,
SUM(IF(command != 'Sleep', 1, 0)) AS active_count
FROM information_schema.processlist
GROUP BY host;
2.5 锁等待
-- InnoDB锁等待信息
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;
-- 或者使用performance_schema
SELECT
r.trx_id AS waiting_trx_id,
w.trx_id AS blocking_trx_id,
r.trx_query AS waiting_query,
w.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id;
三、监控工具三巨头:各自有什么看家本领?
3.1 Zabbix:老牌监控的”厚重”
Zabbix诞生于2001年,是监控领域的”老炮儿”。
核心特点:
- 全功能集成:监控、告警、可视化一站式
- 支持多种采集方式:Agent、SNMP、IPMI、JMX
- 原生支持MySQL模板,开箱即用
- 告警规则灵活,支持多级告警升级
安装MySQL监控(以Zabbix 6.0为例):
# 1. 安装Zabbix Agent
yum install zabbix-agent -y
# 2. 配置Agent连接Server
cat > /etc/zabbix/zabbix_agentd.conf << 'EOF'
Server=192.168.1.100
ServerActive=192.168.1.100
Hostname=mysql-monitor-01
EOF
# 3. 导入MySQL模板
# 在Zabbix Web界面导入 Template DB MySQL
# 下载: https://share.zabbix.com/databases/mysql/zabbix-mysql-getting-started
# 4. 配置MySQL用户权限
mysql -u root -p << 'EOF'
CREATE USER 'zabbix_monitor'@'localhost' IDENTIFIED BY 'StrongPassword123';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'zabbix_monitor'@'localhost';
FLUSH PRIVILEGES;
EOF
# 5. 创建.auth配置文件(无需明文密码)
cat > /etc/zabbix/.my.cnf << 'EOF'
[mysql]
host=localhost
user=zabbix_monitor
password=StrongPassword123
[mysqladmin]
host=localhost
user=zabbix_monitor
password=StrongPassword123
EOF
chmod 600 /etc/zabbix/.my.cnf
# 6. 重启Agent
systemctl restart zabbix-agent
Zabbix的优势:
- 企业级功能完整 - 服务发现、自动注册、分布式监控
- 告警生态成熟 - 邮件、短信、企业微信、钉钉、Slack全支持
- 历史数据存储能力强 - 支持多种存储后端,可长期保留数据
- 无需额外依赖 - Agent + Server + Database,自包含
Zabbix的劣势:
- 学习曲线陡峭 - 模板、触发器、动作配置复杂
- UI相对老旧 - 虽然Zabbix 6.0已改进,但仍不如Grafana美观
- MySQL专项深度不足 - 需要自行调整或集成Percona模板
3.2 Prometheus:云原生时代的”新贵”
Prometheus由SoundCloud在2012年开源,2016年加入CNCF,现在是云原生监控的事实标准。
核心特点:
- Pull-based架构,主动拉取指标
- 强大的查询语言PromQL
- 时间序列数据库,原生支持高基数
- 生态丰富:Exporter模式,任何服务都能监控
MySQL监控架构:
MySQL -> mysqld_exporter -> Prometheus -> Grafana
|
Alertmanager
部署mysqld_exporter:
# 1. 下载并解压
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.14.0/mysqld_exporter-0.14.0.linux-amd64.tar.gz
tar xvf mysqld_exporter-0.14.0.linux-amd64.tar.gz
cd mysqld_exporter-0.14.0.linux-amd64
# 2. 配置MySQL连接信息
cat > .env << 'EOF'
DATA_SOURCE_NAME='exporter:Password123@tcp(127.0.0.1:3306)/'
EOF
# 3. 创建监控用户
mysql -u root -p << 'EOF'
CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'Password123' WITH MAX_USER_CONNECTIONS 3;
GRANT SELECT, PROCESS, REPLICATION CLIENT, SUPER ON *.* TO 'exporter'@'localhost';
FLUSH PRIVILEGES;
EOF
# 4. 启动exporter
./mysqld_exporter --config.my-cnf=.env &
# 默认监听9104端口
# 验证:curl http://localhost:9104/metrics
Prometheus配置文件:
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['192.168.1.50:9104']
labels:
instance: 'mysql-prod-01'
environment: 'production'
- job_name: 'node'
static_configs:
- targets: ['192.168.1.50:9100']
labels:
instance: 'mysql-prod-01'
关键MySQL指标详解:
# QPS(每秒查询数)
rate(mysql_global_status_questions[1m])
# 慢查询速率
rate(mysql_global_status_slow_queries[1m])
# 连接数使用率
mysql_global_status_threads_connected / mysql_global_variables_max_connections
# InnoDB Buffer Pool命中率
(
rate(mysql_global_status_innodb_buffer_pool_read_requests[1m])
- rate(mysql_global_status_innodb_buffer_pool_reads[1m])
) / rate(mysql_global_status_innodb_buffer_pool_read_requests[1m])
# 当前活跃连接
mysql_global_status_threads_running
# 复制延迟(主从架构)
mysql_slave_status_seconds_behind_master
Prometheus的优势:
- 云原生友好 - Kubernetes原生支持,Service Discovery自动发现
- 查询能力强大 - PromQL可以做复杂的时间序列分析
- 生态繁荣 - Alertmanager、Pushgateway、各类Exporter
- 水平扩展好 - 联邦集群、远程存储支持
- 社区活跃 - 持续迭代,CNCF背书
Prometheus的劣势:
- 存储压力大 - 高基数场景下磁盘和内存消耗严重
- 告警配置复杂 - 需要配合Alertmanager
- 没有内置UI - 必须搭配Grafana
- 历史数据有限 - 默认15天,需要长期存储需要额外方案
3.3 Grafana:可视化的”颜值担当”
Grafana本身不是一个监控数据采集系统,而是一个可视化平台。但它和Prometheus的配合堪称黄金搭档。
Grafana的核心价值:
- 多数据源支持(Prometheus、MySQL、InfluxDB、Elasticsearch等)
- 丰富的面板类型
- 强大的告警能力(新版)
- 共享、协作、权限管理
MySQL监控Dashboard配置示例:
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": 7362,
"panels": [
{
"title": "MySQL Overview",
"type": "row",
"panels": [
{
"title": "Uptime",
"type": "stat",
"targets": [
{
"expr": "mysql_global_status_uptime",
"legendFormat": "{{instance}}"
}
]
},
{
"title": "Queries per second",
"type": "graph",
"targets": [
{
"expr": "rate(mysql_global_status_questions[5m])",
"legendFormat": "{{instance}}"
}
]
}
]
}
],
"templating": {
"list": [
{
"name": "instance",
"type": "query",
"datasource": "Prometheus",
"query": "label_values(mysql_up, instance)"
}
]
}
}
Grafana的优势:
- UI美观且灵活 - 拖拽式配置,主题丰富
- 多数据源 - 一个平台看所有监控数据
- 告警规则 - 支持阈值告警、复合告警
- 共享协作 - Dashboard可以分享、导出、版本管理
Grafana的劣势:
- 不是数据采集器 - 需要配合其他系统
- 告警能力相对弱 - 没有Zabbix成熟
- 需要数据源 - 必须搭配Prometheus等
四、实战场景对比:当MySQL真的慢下来时
场景一:生产环境突发慢查询风暴
Zabbix方案:
1. 触发器配置:
Name: MySQL slow queries high
Expression: {Template DB MySQL:mysql.status[Slow_queries].change(5m)}>10
Severity: WARNING
2. 动作配置:
- 发送告警到企业微信
- 执行远程命令:SHOW PROCESSLIST输出到文件
- 创建工单
Prometheus方案:
# alerting.yml
groups:
- name: mysql
rules:
- alert: MySQLSlowQueriesHigh
expr: rate(mysql_global_status_slow_queries[5m]) > 10
for: 2m
labels:
severity: warning
annotations:
summary: "MySQL slow queries high on {{ $labels.instance }}"
description: "Rate of slow queries is {{ $value }} per second"
- alert: MySQLConnection saturation
expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections > 0.8
for: 5m
labels:
severity: critical
annotations:
summary: "MySQL connection pool near limit"
场景二:主从复制延迟告警
# Prometheus告警规则
- alert: MySQLReplicationDelay
expr: mysql_slave_status_seconds_behind_master > 30
for: 1m
labels:
severity: warning
annotations:
summary: "MySQL replication lag on {{ $labels.instance }}"
Zabbix表达式:
{Template DB MySQL:mysql.status[Slave_SQL_Running].last()}=No
or {Template DB MySQL:mysql.status[Slave_IO_Running].last()}=No
or {Template DB MySQL:mysql.status[Seconds_Behind_Master].last(0)}>30
场景三:磁盘I/O打满
# Prometheus + node_exporter
- alert: MySQLDiskIOHigh
expr: rate(node_disk_read_time_seconds[5m]) / rate(node_disk_reads_completed[5m]) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "MySQL disk I/O latency high on {{ $labels.instance }}"
五、选型决策树:你应该选谁?
选择Zabbix的情况:
| 场景 | 说明 |
|---|---|
| 传统IT环境 | 物理机、VM为主,Kubernetes不多 |
| 告警要求严格 | 需要复杂的告警升级、值班表、多级通知 |
| 一站式需求 | 不想集成多个系统,希望开箱即用 |
| 长期数据保留 | 需要保留数月甚至数年的监控历史 |
| 团队熟悉度 | 团队有Zabbix使用经验 |
| 合规要求 | 需要完整的审计日志、操作记录 |
典型用户画像: 银行、政府、传统企业IT部门
选择Prometheus + Grafana的情况:
| 场景 | 说明 |
|---|---|
| 云原生环境 | Kubernetes集群,微服务架构 |
| DevOps文化 | SRE团队,强调自动化和可观测性 |
| 灵活查询需求 | 需要复杂的时间序列分析 |
| 快速迭代 | 监控需求变化快,需要快速调整 |
| 生态集成 | 已经使用或计划使用其他CNCF项目 |
| 可视化要求高 | Dashboard需要美观、交互性强 |
典型用户画像: 互联网企业、科技公司、初创团队
选择Grafana单独的情况:
注意: Grafana通常需要搭配数据源使用。但在以下场景可以考虑:
| 场景 | 说明 |
|---|---|
| 统一监控门户 | 已有多个监控系统,需要统一展示 |
| 业务指标看板 | 需要展示非基础设施指标 |
| 快速原型 | 快速搭建临时监控面板 |
六、混合方案:最佳实践是”我全都要”
在实际生产环境中,很多团队选择混合方案:
┌─────────────────────────────────────────────────────────────┐
│ 统一监控平台架构 │
├─────────────────────────────────────────────────────────────┤
│ Zabbix Prometheus Grafana │
│ ├─ 服务器监控 ├─ MySQL指标 ├─ 可视化 │
│ ├─ 网络设备 ├─ 应用APM ├─ 告警管理 │
│ ├─ 存储监控 ├─ K8s监控 ├─ 统一Dashboard│
│ └─ 传统告警 └─ 时序分析 └─ 多数据源 │
│ │
│ Alertmanager ──→ 企业微信/钉钉/邮件 │
└─────────────────────────────────────────────────────────────┘
具体配置示例:
# Prometheus scrape MySQL
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['192.168.1.50:9104']
# Alertmanager配置
receivers:
- name: 'wechat'
wechat_configs:
- corp_id: 'your_corp_id'
to_party: 'party_id'
agent_id: 'agent_id'
api_secret: 'your_secret'
七、MySQL专项监控指标清单
无论选择哪个工具,以下指标都需要关注:
7.1 性能指标
-- 获取关键指标
SELECT
@@max_connections AS max_connections,
@@innodb_buffer_pool_size / 1024 / 1024 / 1024 AS buffer_pool_gb,
@@innodb_log_file_size / 1024 / 1024 AS log_file_mb,
@@innodb_io_capacity AS io_capacity,
@@query_cache_size / 1024 / 1024 AS query_cache_mb,
@@table_open_cache AS table_open_cache,
@@thread_cache_size AS thread_cache_size;
7.2 运行指标
| 指标类别 | 关键指标 | 告警阈值参考 |
|---|---|---|
| 连接 | Threads_connected | > 80% max_connections |
| 查询 | QPS/TPS | 突增50%以上 |
| 慢查询 | Slow_queries | 持续增长 |
| 缓存 | Buffer pool hit rate | < 95% |
| 锁 | Table locks waited | 持续增加 |
| 复制 | Replication lag | > 30s |
| 磁盘 | Disk usage | > 85% |
| 网络 | Network bytes | 突增 |
八、从监控到告警:闭环的关键一步
监控只是第一步,真正的价值在于”发现问题 → 定位问题 → 解决问题 → 复盘优化”的闭环。
告警级别定义:
# 建议的告警分级
P0 - Critical:
- MySQL完全不可用
- 数据丢失风险
- 响应时间:< 1分钟
P1 - High:
- 性能严重下降
- 主从复制中断
- 响应时间:< 5分钟
P2 - Medium:
- 性能轻微下降
- 个别慢查询
- 响应时间:< 30分钟
P3 - Low:
- 容量预警
- 配置变更提醒
- 响应时间:< 24小时
告警抑制与合并:
# Alertmanager路由配置
route:
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'oncall-pager'
repeat_interval: 1h
- match:
alertname: MySQLConnectionHigh
continue: true # 继续匹配其他规则
receiver: 'slack'
九、一些实战中的”坑”与应对
坑1:监控本身拖慢MySQL
-- 错误做法:直接查询information_schema
SELECT * FROM information_schema.tables; -- 大表时非常慢
-- 正确做法:使用performance_schema
SET profiling = 1;
SELECT * FROM performance_schema.setup_consumers;
建议: Exporter方式比直接查询性能好得多。
坑2:告警风暴
问题:100台MySQL,某时刻同时触发1000条告警
解决:
1. 告警合并:相同类型的告警合并为一条
2. 告警抑制:主库告警时,从库相关告警抑制
3. 静默规则:维护时段静默非关键告警
坑3:监控盲区
常见盲区:
- 只监控可用,不监控健康
- 只看平均值,忽略分位数
- 只监控数据库层,忽略操作系统层
- 只有数字告警,没有业务告警
建议:建立"多层监控"体系
- 基础设施层:CPU、内存、磁盘、网络
- MySQL层:连接、查询、锁、缓存
- 应用层:响应时间、错误率、业务指标
- 用户层:用户体验、核心流程成功率
十、给你的建议:从小处着手,持续迭代
回到老王的故事,如果他想要建立一个完善的MySQL监控体系,我建议按以下步骤:
第一阶段(1周):基础监控到位
1. 部署Zabbix Agent或mysqld_exporter
2. 配置基本指标采集(连接数、QPS、慢查询)
3. 设置基础告警(连接数>80%、慢查询突增)
4. 搭建简单的Dashboard
第二阶段(2周):完善告警体系
1. 定义告警分级和响应流程
2. 配置多渠道通知(微信、邮件、电话)
3. 建立值班表和On-Call轮转
4. 编写常见故障的应急手册
第三阶段(1月):深度优化
1. 引入APM工具,实现SQL级追踪
2. 建立容量规划模型
3. 配置自动扩缩容策略
4. 定期进行监控演练
第四阶段(持续):数据驱动
1. 分析监控数据,发现性能瓶颈
2. 建立基线,实现异常检测
3. 预测性维护,提前扩容
4. 持续优化监控策略
十一、总结
| 维度 | Zabbix | Prometheus + Grafana |
|---|---|---|
| 学习成本 | 高 | 中 |
| 部署复杂度 | 中 | 中低 |
| MySQL监控深度 | 中(需定制) | 高(生态丰富) |
| 告警能力 | 强 | 中(需配置) |
| 可视化 | 一般 | 优秀 |
| 云原生支持 | 弱 | 强 |
| 长期存储 | 好 | 需额外方案 |
| 适合场景 | 传统企业 | 互联网/云原生 |
我的建议:
如果你的环境是传统架构、强调稳定性、有成熟运维团队,选Zabbix。
如果你的环境是云原生、快速迭代、有DevOps文化,选Prometheus + Grafana。
如果两者兼有,像上面说的那样,混合方案往往是最优解。
记住,监控不是一劳永逸的项目,而是一个持续迭代的过程。最好的监控体系,是能在问题发生前预警、发生时快速定位、发生后辅助复盘的系统。
希望这篇文章能帮到你。如果有任何问题,欢迎在评论区交流——毕竟,独乐乐不如众乐乐,大家都能少熬几个夜,才是真的。
