如果你正在运营一个稍微有点规模的应用,或者只是单纯地想让你的数据库跑得再顺一点,那你肯定有过这样的时刻:深夜三点,报警电话响起,应用访问速度慢得像是在爬楼梯,而你站在服务器前面,感觉自己对发生了什么一无所知。
别慌,这种时候,你需要的不是一双火眼金睛,而是一套趁手的监控工具。MySQL的世界很庞大,监控工具更是琳琅满目,从命令行的一行指令到可视化大屏,从内置的性能_schema到第三方的Prometheus,选对工具并能熟练驾驭,才是解决性能问题的关键。
今天,我就带你把这套“装备库”从头到尾捋一遍。我们不讲枯燥的说明书,而是像老朋友聊天一样,把这些工具怎么用、什么时候用、以及背后的原理掰开揉碎讲清楚。
第一章:基础中的基础——这些命令你必须会
在引入任何昂贵的商业软件之前,我们先看看MySQL自带的那些“原生武器”。它们无处不在,无需安装,且功能强大到令人发指。
1. SHOW PROCESSLIST:第一眼诊断神器
当你发现数据库卡顿时,第一步永远是看当前在跑什么。SHOW PROCESSLIST 就是这个角色。
SHOW PROCESSLIST;
输出结果里有几个关键字段:
- Id:连接ID。
- User:哪个用户连进来的。
- Host:来源IP,如果是
127.0.0.1,通常是本地应用;如果是远程,就得警惕是不是异常访问。 - db:正在操作的数据库。
- Command:连接状态,
Sleep表示空闲,Query表示正在执行,Connect表示刚连上。 - Time:该查询已运行了多少秒。这个数字是核心,超过几十秒的查询通常就是元凶。
- State:执行状态,比如
Sending data,Sorting result,Locked等。 - Info:具体的SQL语句。
实战技巧:如果看到大量的 Sleep,说明连接池配置有问题,或者应用没有正确关闭连接。如果看到 Locked,那大概率是发生了锁竞争。
2. SHOW STATUS:全局视角的体检报告
SHOW PROCESSLIST 看的是“现在”,SHOW STATUS 看的是“历史”。它记录了MySQL服务器自启动以来的所有统计信息。
-- 查看所有状态变量
SHOW GLOBAL STATUS;
-- 只看跟查询相关的,用 LIKE 过滤
SHOW GLOBAL STATUS LIKE 'Handler%';
SHOW GLOBAL STATUS LIKE 'Questions';
SHOW GLOBAL STATUS LIKE 'Slow_queries';
这里有几个关键指标,你得熟记于心:
- Threads_connected:当前打开的连接数。
- Threads_running:当前正在执行查询的线程数。如果这个值长期接近
max_connections,那你的数据库要爆了。 - Questions:发送给服务器的查询总数。
- Slow_queries:慢查询的数量。
- Handler_read_rnd_next:从数据文件中读取下一行的请求数。如果这个值很高,说明有大量的全表扫描或乱序读取。
3. SHOW PROFILE:逐行剖析查询的显微镜
当你定位到一个慢查询,但不知道它慢在哪里时,SHOW PROFILE 就是你的解剖刀。
-- 开启 profiling
SET profiling = 1;
-- 执行你的慢查询
SELECT * FROM large_table WHERE status = 'pending' ORDER BY create_time;
-- 查看所有 profile
SHOW PROFILES;
-- 查看具体某个 query_id 的详情
SHOW PROFILE FOR QUERY 1;
-- 更详细的 CPU 和内存信息
SHOW PROFILE ALL FOR QUERY 1;
输出结果会告诉你,查询在 starting、checking permissions、opening tables、sorting result、sending data 各个阶段花了多少时间。注意:SHOW PROFILE 在 MySQL 8.0 中被标记为废弃,推荐迁移到 Performance Schema(后面会讲),但在老版本里,它依然是最快定位瓶颈的工具。
第二章:深度内探——Performance Schema
MySQL 5.5 引入,5.7 优化,8.0 成为默认的监控基石。Performance Schema 是 MySQL 内部的一个子系统,专门用于监控数据库执行的细节。它比 SHOW STATUS 更细粒度,比 SHOW PROFILE 更持久。
为什么选择 Performance Schema?
传统的监控工具大多只提供聚合数据(比如总耗时多少),而 Performance Schema 能提供事件级的数据。你可以看到每一次函数调用、每一次表锁、每一次语句执行的具体细节。
核心配置:别让它拖慢数据库
Performance Schema 是有开销的,默认配置可能过于详细,对生产环境压力大。我们需要精简它。
-- 查看当前配置
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%wait%';
-- 关闭大部分不常用的等待事件,只保留关键的
UPDATE performance_schema.setup_instruments
SET ENABLED = 'NO', TIMED = 'NO'
WHERE NAME NOT IN (
'wait/io/table/sql/handler',
'wait/io/file/sql/ibd',
'statement/sql/select',
'statement/sql/update',
'statement/sql/delete',
'statement/sql/insert'
);
-- 同时,也要过滤掉系统库和内部线程的监控
UPDATE performance_schema.setup_consumers
SET ENABLED = 'NO'
WHERE NAME IN ('events_statements_history_long', 'events_waits_history_long', 'objects_summary_global_by_event_name');
实战查询:找出最耗时的SQL
-- 查看历史上执行时间最长的 SQL
SELECT
DIGEST_TEXT AS `SQL摘要`,
COUNT_STAR AS `执行次数`,
SUM_TIMER_WAIT / 1000000000000 AS `总耗时(秒)`,
AVG_TIMER_WAIT / 1000000000000 AS `平均耗时(秒)`,
MAX_TIMER_WAIT / 1000000000000 AS `最大耗时(秒)`
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
这段查询非常有用。它告诉你哪些SQL占据了大部分服务器资源。注意 DIGEST_TEXT,这是MySQL对SQL进行指纹化后的结果,能把参数不同的相同结构SQL归为一类,比如 SELECT * FROM t WHERE id = 1 和 SELECT * FROM t WHERE id = 2 会被归为同一类。
监控锁等待
锁是性能杀手。通过 Performance Schema,你可以实时监控锁事件。
-- 查看当前的锁等待情况
SELECT
THREAD_ID,
EVENT_NAME,
TIMER_WAIT / 1000000000000 AS `等待时间(秒)`,
OBJECT_SCHEMA,
OBJECT_NAME
FROM performance_schema.events_waits_current
WHERE EVENT_NAME LIKE '%lock%';
第三章:慢查询日志——时间的沉淀
Slow Query Log 是MySQL最经典、最可靠的性能监控工具。它记录了所有执行时间超过 long_query_time 阈值的SQL。
如何开启和优化慢查询日志
-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 设置阈值,比如 1 秒
SET GLOBAL long_query_time = 1;
-- 记录没有使用索引的查询(可选,但很有用)
SET GLOBAL log_queries_not_using_indexes = ON;
解析慢查询日志
慢查询日志是文本格式,直接打开看会很痛苦。我们需要工具来解析它。
1. mysqldumpslow:MySQL自带
# 按查询时间排序,显示前10条
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 按查询次数排序
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
# 只显示包含特定关键字的查询
mysqldumpslow -s t -t 10 -g "select" /var/log/mysql/slow.log
2. pt-query-digest:Percona Toolkit 之王
如果说有一个工具能取代所有慢查询分析工具,那一定是 pt-query-digest。它是Perl写的,功能极其强大。
# 分析慢查询日志
pt-query-digest /var/log/mysql/slow.log
# 输出摘要报告,直接看关键指标
pt-query-digest --report /var/log/mysql/slow.log
# 生成 HTML 报告,带图表
pt-query-digest --report --output=html /var/log/mysql/slow.log > report.html
# 对正在运行的慢查询进行实时分析(需要开启 performance schema)
pt-query-digest --review h=localhost,D=test,t=query_review
pt-query-digest 的输出非常直观,它会告诉你:
- Query #1: 最慢的查询是什么。
- Time range: 查询发生的时间范围。
- Exec time: 执行时间分布。
- Lock Time: 锁等待时间。
- Rows sent: 返回行数。
- Examined rows: 扫描行数。
- Fingerprint: 查询指纹。
真实案例:有一次,我们公司的订单服务偶发性超时。通过分析 pt-query-digest 生成的报告,我们发现有一个分页查询,每次都要扫描几十万次行数据,但只返回10条。原因是 ORDER BY 的字段没有索引,导致文件排序。加上索引后,执行时间从几秒降到了几十毫秒。
第四章:现代可观测性——Prometheus + Grafana
传统的监控工具往往是一堆数字和日志,缺乏直观性和趋势分析。在云原生时代,Prometheus 和 Grafana 的组合成为了事实标准。
架构简述
- Exporter:从MySQL采集指标的组件。常用的是
mysqld_exporter(Prometheus官方)或mysql_exporter(Percona)。 - Prometheus:时序数据库,负责存储和拉取指标。
- Grafana:可视化平台,负责展示图表。
部署 mysqld_exporter
# docker-compose.yml 示例
version: '3'
services:
mysqld_exporter:
image: prom/mysqld-exporter
environment:
- DATA_SOURCE_NAME=exporter:exporter@tcp(mysql:3306)/
ports:
- "9104:9104"
depends_on:
- mysql
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
Prometheus 配置
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'mysql'
static_configs:
- targets: ['mysqld_exporter:9104']
关键监控指标
在Grafana中,你可以导入官方的Dashboard模板(ID: 7362),然后关注以下几个核心指标:
MySQL Connections:
mysqld_global_threads_connected:当前连接数。mysqld_global_threads_created:创建线程总数。如果增长过快,说明连接泄漏。
MySQL Queries:
mysqld_global_queries:总查询数。mysqld_global_questions:发送给服务器的查询数。
MySQL InnoDB Row Operations:
mysqld_global_innodb_rows_read:读取行数。mysqld_global_innodb_rows_deleted:删除行数。- 这些指标能反映表的负载情况。
MySQL InnoDB Buffer Pool:
mysqld_global_innodb_buffer_pool_pages_free:空闲页数。mysqld_global_innodb_buffer_pool_read_requests:缓冲池读请求。- 计算缓存命中率:
(1 - rows_read / read_requests) * 100。理想情况应大于95%。
MySQL QPS/TPS:
- 每秒查询数(QPS)和每秒事务数(TPS)是衡量数据库吞吐量的核心指标。
Grafana Dashboard 实战
一个好的Grafana面板应该包含:
- 总体概览:QPS、TPS、连接数、慢查询数。
- 性能趋势:CPU使用率、内存使用率、IO等待。
- InnoDB细节:缓冲池命中率、锁等待、临时表创建。
- 复制状态(如果是主从架构):延迟时间、线程状态。
第五章:云原生的恩赐——云厂商监控工具
如果你使用的是阿里云RDS、AWS RDS、腾讯云CDB等云服务,恭喜你,你不需要自己部署Exporter和Prometheus。云厂商提供了开箱即用的监控服务。
阿里云 RDS 性能洞察
阿里云的“性能洞察”功能非常强大。它不仅仅是展示图表,还能自动分析慢查询,并给出优化建议。
- SQL洞察:记录所有SQL的执行情况,支持按时间、SQL文本、执行耗时等维度检索。
- 慢日志分析:自动聚合慢查询,按耗时、频率、扫描行数等排序。
- 索引推荐:基于历史查询,自动推荐可能缺失的索引。
AWS RDS Performance Insights
AWS的Performance Insights用热力图(Heatmap)来展示数据库的负载来源。
- DB Load:数据库的总负载。
- Wait Events:负载是由什么引起的?是CPU忙?还是IO等待?还是锁等待?
- Top SQL:哪些SQL占据了大部分负载?
热力图的优势在于,它能让你一眼看出负载的“热点”。比如,如果某段时间DB Load飙升,且热力图显示主要是io事件,那你就可以确定是磁盘IO瓶颈,而不是CPU问题。
腾讯云上云数据库监控
腾讯云提供了类似的“性能洞察”和“慢查询分析”功能,并且与云监控(CloudMonitor)深度集成,支持自定义告警规则。
第六章:企业级商业工具——Datadog, New Relic, Dynatrace
对于大型企业和对稳定性要求极高的场景,开源工具可能需要额外的维护成本。这时候,商业监控工具的价值就体现出来了。
Datadog for MySQL
Datadog提供了一键部署的MySQL集成。它的优势在于:
- 全栈监控:不仅能监控MySQL,还能监控宿主机、容器、网络、日志等。
- 智能告警:基于机器学习,能自动识别异常模式,减少误报。
- 服务级别目标(SLO):可以定义数据库的可用性SLO,并实时追踪。
New Relic
New Relic的特色是“数字智能”,它能将数据库性能与应用性能(APM)关联起来。比如,你可以看到某个慢查询是由哪个微服务、哪个API调用触发的,从而形成完整的调用链分析。
Dynatrace
Dynatrace以其自动发现和问题根因分析著称。它会自动发现MySQL实例,配置监控,并在检测到问题时,自动分析可能的原因,给出修复建议。
第七章:实战场景与工具选择指南
面对这么多工具,你可能会问:我该怎么选?
这里给你几个常见的实战场景:
场景一:初创公司,资源有限,MySQL小规模使用
- 首选:
SHOW PROCESSLIST+SHOW STATUS+ 慢查询日志 +mysqldumpslow。 - 理由:零成本,无需额外部署,能满足基本的诊断需求。定期查看慢查询日志,及时优化SQL。
场景二:中型企业,有一定规模,追求稳定性
- 首选:
Performance Schema+pt-query-digest+ Prometheus + Grafana。 - 理由:Prometheus + Grafana 提供了可视化的趋势分析,能提前发现性能退化。
pt-query-digest用于深度分析慢查询。这套组合是开源界的黄金标准,社区支持好,文档丰富。
场景三:大型互联网平台,高并发,复杂架构
- 首选:Prometheus + Grafana + 自定义Exporter + 商业工具(如Datadog/New Relic)+ 云厂商监控(如AWS PI)。
- 理由:需要多维度、全栈的监控。商业工具提供智能告警和SLO管理,云厂商监控提供底层的资源视图,自建Prometheus提供灵活的自定义指标。
场景四:紧急故障排查
- 第一步:
SHOW PROCESSLIST查看当前卡住的查询。 - 第二步:
SHOW STATUS LIKE 'Threads_running'看并发量。 - 第三步:如果有性能洞察工具(如AWS PI或阿里云),查看近期的负载热力图。
- 第四步:分析慢查询日志,使用
pt-query-digest找出高频慢查询。 - 第五步:对可疑SQL使用
EXPLAIN分析执行计划。
第八章:被忽视的“监控”——EXPLAIN 和执行计划
最后,我想强调一个概念:监控不仅是看数字,更是理解行为。
EXPLAIN 是MySQL提供的用于分析SQL执行计划的工具。它不是传统意义上的监控工具,但它能告诉你MySQL“打算”怎么执行你的查询。
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'pending' ORDER BY create_time DESC LIMIT 10;
关注以下几个字段:
- type:访问类型。
system>const>eq_ref>ref>range>index>ALL。越往后越差。ALL是全表扫描,必须避免。 - key:实际使用的索引。如果为 `
