4. 数据库监控(上):Oracle/MySQL关键性能指标、慢查询监控、连接池监控
数据库监控,说白了就是给ERP系统的心脏做体检。我做了这么多年运维,见过太多因为数据库问题导致整个业务瘫痪的案例。有一次,一个客户的ERP系统在月底结算时突然卡死,最后发现是连接池爆了。嗯,从那以后,我对数据库监控就格外上心。
今天咱们先聊上半部分,重点讲三个核心模块:关键性能指标、慢查询监控、连接池监控。这些都是日常运维中必须盯紧的。
4.1 关键性能指标(KPI)
我个人习惯,先把数据库的KPI分成两类:资源类和效率类。资源类告诉你数据库吃不吃力,效率类告诉你数据库干不干活。
4.1.1 Oracle关键指标
| 指标类别 | 指标名称 | 正常范围 | 告警阈值 |
|---|---|---|---|
| 资源类 | CPU使用率 | < 70% | > 85% 持续5分钟 |
| 资源类 | 内存使用率(SGA+PGA) | < 80% | > 90% |
| 资源类 | 磁盘IO等待时间 | < 10ms | > 20ms |
| 效率类 | 每秒事务数(TPS) | 根据业务基线 | 下降超过30% |
| 效率类 | 缓冲区命中率 | > 99% | < 95% |
| 效率类 | 硬解析率 | < 1% | > 5% |
这里我特别想强调一下硬解析率。Oracle的SQL执行流程中,硬解析是非常消耗CPU的操作。我在项目中遇到过,一个ERP模块上线后,数据库CPU直接飙到100%。查了半天,发现是代码里拼接SQL导致大量硬解析。后来改成绑定变量,CPU直接降到20%。
Oracle监控脚本示例(检查硬解析率):
SELECT
ROUND(100 * (1 - (SUM(EXECUTIONS) / SUM(PARSE_COUNT))), 2) AS hard_parse_ratio
FROM V$SQLAREA
WHERE PARSE_COUNT > 0;
4.1.2 MySQL关键指标
MySQL的监控思路和Oracle类似,但指标名称和关注点略有不同。你想想看,MySQL的InnoDB引擎和Oracle的架构差异还是挺大的。
| 指标类别 | 指标名称 | 正常范围 | 告警阈值 |
|---|---|---|---|
| 资源类 | QPS(每秒查询数) | 根据业务基线 | 超过基线50% |
| 资源类 | InnoDB缓冲池命中率 | > 99% | < 95% |
| 资源类 | 临时表创建率 | < 10次/秒 | > 50次/秒 |
| 效率类 | 慢查询数量 | < 5次/分钟 | > 20次/分钟 |
| 效率类 | 锁等待次数 | < 1次/秒 | > 5次/秒 |
我的经验:MySQL的临时表创建率是个容易被忽略的指标。如果这个值突然升高,通常意味着SQL没有走索引,或者排序操作过多。我曾经排查过一个案例,就是临时表创建率从5飙到200,最后发现是一个报表查询没有加limit。
4.2 慢查询监控
慢查询,是数据库性能问题的头号杀手。说白了,就是SQL执行得太慢,拖累了整个系统。我见过最夸张的一次,一个慢查询跑了8分钟,直接把ERP的订单录入功能给堵死了。
4.2.1 Oracle慢查询监控
Oracle的慢查询监控,我主要用两个视图:V$SQL 和 DBA_HIST_SQLSTAT。前者看实时,后者看历史。
实时监控慢查询:
SELECT
SQL_ID,
ROUND(ELAPSED_TIME / 1000000, 2) AS elapsed_seconds,
EXECUTIONS,
ROUND(ELAPSED_TIME / DECODE(EXECUTIONS, 0, 1, EXECUTIONS) / 1000000, 2) AS avg_time,
SQL_TEXT
FROM V$SQL
WHERE ELAPSED_TIME / DECODE(EXECUTIONS, 0, 1, EXECUTIONS) > 1000000
ORDER BY avg_time DESC
FETCH FIRST 10 ROWS ONLY;
这个查询会找出平均执行时间超过1秒的SQL。我个人习惯把阈值设成500毫秒,因为ERP系统对响应时间要求比较高。
注意:Oracle的 V$SQL 视图在实例重启后会清空。如果你需要长期监控,建议用 DBA_HIST_SQLSTAT 历史视图。我曾经吃过这个亏,重启后查不到历史数据,排查问题费了好大劲。
4.2.2 MySQL慢查询监控
MySQL的慢查询监控相对简单。首先,确保开启了慢查询日志:
-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
-- 开启慢查询日志(生产环境建议开启)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 超过1秒的记录
SET GLOBAL log_queries_not_using_indexes = ON;
然后,用 mysqldumpslow 工具分析日志:
# 按平均查询时间排序,显示前10条
mysqldumpslow -t 10 -s at /var/log/mysql/slow.log
# 按执行次数排序
mysqldumpslow -t 10 -s c /var/log/mysql/slow.log
嗯,这里要注意。慢查询日志如果一直开着,文件会变得很大。我建议设置一个合理的轮转策略,比如每天切割一次,保留7天。
4.3 连接池监控
连接池,是ERP系统最容易出问题的地方之一。你想想看,ERP系统通常有成百上千个并发用户,如果每个请求都新建一个数据库连接,数据库根本扛不住。连接池的作用就是复用连接,但一旦配置不当,就会出大问题。
4.3.1 连接池的核心指标
| 指标 | 说明 | 正常范围 | 告警阈值 |
|---|---|---|---|
| 活跃连接数 | 当前正在执行SQL的连接数 | < 最大连接数的80% | > 90% |
| 空闲连接数 | 空闲等待的连接数 | 最大连接数的10%-20% | < 5% 或 > 50% |
| 等待连接数 | 等待获取连接的请求数 | 0 | > 0 持续10秒 |
| 连接超时次数 | 获取连接超时的次数 | 0 | > 0 |
我的经验:等待连接数这个指标,一旦大于0,就意味着系统已经出现瓶颈了。我曾经处理过一个案例,ERP系统每天早上9点准时卡顿,查了监控发现等待连接数在8:55开始飙升,到9:05达到峰值。最后发现是定时任务和用户登录高峰撞在一起了。解决方案很简单,把定时任务推迟到10点执行。
4.3.2 Oracle连接池监控
Oracle的连接池监控,我通常看 V$SESSION 和 V$RESOURCE_LIMIT:
-- 查看当前会话状态
SELECT
COUNT(*) AS total_connections,
SUM(CASE WHEN STATUS = 'ACTIVE' THEN 1 ELSE 0 END) AS active_connections,
SUM(CASE WHEN STATUS = 'INACTIVE' THEN 1 ELSE 0 END) AS idle_connections
FROM V$SESSION;
-- 查看连接数限制
SELECT
RESOURCE_NAME,
CURRENT_UTILIZATION,
MAX_UTILIZATION,
LIMIT_VALUE
FROM V$RESOURCE_LIMIT
WHERE RESOURCE_NAME IN ('sessions', 'processes');
4.3.3 MySQL连接池监控
MySQL的连接池监控相对简单,主要看 SHOW STATUS 和 SHOW VARIABLES:
-- 查看当前连接状态
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW STATUS LIKE 'Threads_cached';
SHOW STATUS LIKE 'Connections';
-- 查看最大连接数配置
SHOW VARIABLES LIKE 'max_connections';
-- 查看连接超时配置
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';
避坑指南:我曾经遇到过一个问题,MySQL的 wait_timeout 设置得太长(默认8小时),导致大量空闲连接占着连接池不放。后来我把 wait_timeout 改成300秒(5分钟),连接池的压力一下子就降下来了。但要注意,如果应用层有长连接需求,这个值不能设得太短,否则会频繁断开重连。
4.4 总结与建议
好了,今天的内容就到这里。我总结几个要点:
- 关键指标要盯紧:资源类指标看CPU、内存、IO;效率类指标看TPS、命中率、解析率。
- 慢查询是头号敌人:Oracle用
V$SQL和DBA_HIST_SQLSTAT,MySQL用慢查询日志 +mysqldumpslow。 - 连接池要防爆:重点关注等待连接数和连接超时次数,这两个指标一旦大于0,就要立刻排查。
下一节,我们会继续聊数据库监控的下半部分:表空间监控、锁监控、以及备份监控。这些都是实战中经常用到的技能,到时候我会分享更多踩坑经验。
记住一句话:数据库监控不是为了看数据,而是为了在问题发生前就发现它。嗯,这才是监控的真正价值。