监控是运维的眼睛。没有监控,数据库就是在裸奔。MySQL 的运行状态监控不需要大而全,但必须抓住几个关键指标:连接数、QPS、TPS、缓存命中率。它们分别反映了数据库的入口容量、吞吐能力、写入性能和内存利用效率。掌握这些指标,你就能在问题萌芽时及时发现,而不是等用户投诉后才手忙脚乱。
22.1.1 连接数:数据库的接待能力
连接数直接决定了数据库能同时服务多少客户端。一旦连接数打满,新的连接请求会被拒绝,业务直接报错。因此,连接数监控是优先级最高的告警项之一。
核心指标
| 指标 | 含义 | 查看方式 |
|------|------|----------|
| Threads_connected | 当前已建立的连接数 | SHOW STATUS LIKE 'Threads_connected'; |
| Threads_running | 当前正在执行语句的连接数(非空闲) | SHOW STATUS LIKE 'Threads_running'; |
| Max_used_connections | 自服务启动以来曾达到的最高并发连接数 | SHOW STATUS LIKE 'Max_used_connections'; |
| max_connections | 服务器允许的最大连接数(配置参数) | SHOW VARIABLES LIKE 'max_connections'; |
| Connection_errors_max_connections | 因超过最大连接数而被拒绝的次数 | SHOW STATUS LIKE 'Connection_errors_max_connections'; |
监控重点
Threads_connected/max_connections的比值:通常告警阈值设置为 80%。如果连接数持续接近上限,要么是连接池配置不合理(应用端没有及时释放连接),要么是真的需要扩大max_connections,或者增加从库进行读写分离。Threads_running突然飙升:这往往意味着有大量 SQL 在执行堆积,可能是慢查询阻塞了后续请求,或者锁等待导致连接没办法及时释放。正常业务下,运行中的线程数应该远小于总连接数。如果持续大于CPU 核数 × 2,就要高度警惕了。Connection_errors_max_connections大于 0:说明历史上发生过连接拒绝,这是一个很差的信号,说明峰值时业务已经受到了影响。
实用操作
生产环境建议将 max_connections 设置得比日常峰值高出 30% 左右,留足缓冲。如果应用使用连接池,应该让应用侧的最大连接总数加上监控、备份等工具的连接数,始终小于 max_connections。可以通过 SHOW PROCESSLIST 或 sys.session 视图快速检查当前连接的来源和状态,查找大量 Sleep 连接的来源。
22.1.2 QPS 与 TPS:数据库的吞吐能力
QPS(Queries Per Second)和 TPS(Transactions Per Second)是衡量数据库负载最经典的两个指标。很多人容易把它们混为一谈,但含义是不一样的:
- QPS:每秒执行的查询数,包括所有类型的 SQL(SELECT、INSERT、UPDATE、DELETE 等)。它反映的是数据库的整体语句执行频度。
- TPS:每秒执行的事务数,关注的是逻辑上的完整业务操作。一个事务可能包含多条 SQL,因此 TPS 通常 ≤ QPS。
如何计算
MySQL 本身不直接提供 QPS 和 TPS 的即时值,但我们可以通过两个全局状态变量来计算:
QPS ≈ (新采集的 Questions - 上次采集的 Questions) / 时间间隔
TPS ≈ (新采集的 Com_commit + Com_rollback - 上次采集的 Com_commit - 上次采集的 Com_rollback) / 时间间隔
涉及的变量:
| 变量 | 含义 |
|------|------|
| Questions | 服务器启动以来所有客户端发送的语句数(不包含存储过程内的语句,也不含 COM_PING 等命令) |
| Com_commit | 提交的事务总数 |
| Com_rollback | 回滚的事务总数 |
可以通过 SHOW GLOBAL STATUS 采集这些值,然后用监控系统(如 Prometheus + mysqld_exporter)进行差值计算并绘图。mysqld_exporter 会直接暴露 mysql_global_status_questions 等指标,配合 rate() 函数即可计算每秒速率。
合理范围与告警
QPS 和 TPS 没有绝对的“正常值”,它们高度依赖业务量和硬件能力。更重要的是趋势变化:
- 突发下降:QPS/TPS 突然跌到接近 0,通常意味着数据库锁死、连接耗尽、或主从故障导致写入中断。
- 异常飙升:短时间内 QPS 翻倍,可能是缓存穿透、定时任务集中触发、或被攻击扫表。需要结合
Threads_running和慢查询一起分析。 - 回滚率异常:
Com_rollback与(Com_commit + Com_rollback)的比值突增,说明有大量事务执行失败,可能是死锁、约束冲突或业务逻辑错误。
监控 QPS/TPS 的主要价值在于建立基线。你应该知道你业务高峰期的 QPS 通常是 5000 还是 50000,一旦偏离基线,就要立刻查看原因。
22.1.3 缓存命中率:缓冲池的价值
对于 InnoDB,最重要的缓存就是缓冲池(Buffer Pool)。缓存命中率直接体现了内存配置是否足够,以及磁盘 I/O 的压力大小。如果命中率很低,大量请求不得不读磁盘,性能会急剧下降。
核心指标
| 指标 | 含义 |
|------|------|
| Innodb_buffer_pool_read_requests | 向缓冲池发出的逻辑读请求总数 |
| Innodb_buffer_pool_reads | 缓冲池未命中,必须从磁盘读取的页数 |
命中率计算公式
InnoDB 缓冲池命中率 = (Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests × 100%
这两个变量都可以从 SHOW GLOBAL STATUS 中获取,监控系统同样通过差值计算实时命中率。
合理值
对于在线业务,缓冲池命中率通常应该维持在 99% 以上,理想情况接近 100%。如果你的命中率持续低于 95%,说明缓冲池大小相较热数据量严重不足,磁盘读成为瓶颈。
但也要注意,不能只看命中率。刚启动时命中率天然偏低,预热一段时间后会自然上升。因此,关注命中率的长期趋势比瞬时值更有意义。如果命中率在业务上升期持续下滑,就需要考虑扩大 innodb_buffer_pool_size,或者优化 SQL 索引以减少要扫描的数据量。
另外,还有两个辅助的缓存相关指标值得关注:
Innodb_buffer_pool_pages_dirty:当前脏页数量。如果脏页积压过多,说明刷盘压力大,可能导致 checkpoint 时性能抖动。Innodb_buffer_pool_wait_free:等待空闲页的次数。如果大于 0,说明缓冲池空间紧张,有写入被阻塞,严重影响性能。
监控建议
生产环境至少为缓冲池分配服务器内存的 60%~80%。命中率低于 99% 时就应该告警,提醒 DBA 或开发人员排查是否存在全表扫描、索引缺失或缓存大小不合理的情况。
22.1.4 其他值得顺手监控的辅助指标
除了上述四大核心指标,还有几个开销极低但很有价值的监控点,建议一并采集:
Innodb_row_lock_waits:行锁等待次数。如果这个值在单位时间内出现明显增长,说明有热点行竞争或死锁风险。Slow_queries:慢查询总数。配合慢查询日志,可以快速发现执行效率低下的 SQL。Aborted_connects:连接失败的次数(如密码错误、权限不足),可用于安全告警。Questions与Queries的差值:Queries包含存储过程中的语句,Questions不包含。二者差异较大通常意味着大量使用了存储过程。Bytes_received和Bytes_sent:网络流量,配合带宽监控,分析是否为网络 I/O 瓶颈。
22.1.5 监控工具落地建议
不要手动去查这些状态值,要借助自动化工具。一个实用的组合是:
- 采集:使用
mysqld_exporter作为 Prometheus 的 exporter,它会自动采集上述所有关键指标,暴露为 Prometheus 的 metric。 - 可视化:Grafana 有大量成熟的 MySQL 监控仪表盘模板(如 Percona 提供的模板),导入即可看到连接数、QPS、TPS、命中率、锁等待等曲线的历史趋势。
- 告警:在 Prometheus 中配置 Alertmanager 规则,针对连接数使用率 > 80%、命中率 < 95% 持续 5 分钟、回滚率突增等设置多渠道通知(企业微信、钉钉、短信)。
如果规模较小或者运维资源有限,也可以直接使用云 RDS 自带的监控平台,它们已经默认集成了这些关键指标的监控和告警功能。
归根结底,运行状态监控不是为了看漂亮的曲线,而是为了能快速回答三个问题:数据库能不能连接?跑得动吗?跑的稳不稳? 连接数、QPS/TPS、缓存命中率,就分别回答了这三个问题。记住这些指标及其告警阈值,你就能在大多数常见故障发生前抢占先机。