简介:面向数据库管理员与运维人员的监测指标参考文档,集中梳理Oracle、SQL Server、Sybase、Informix等主流数据库在性能、内存、锁与死锁、表空间、I/O读写、连接与缓存等维度的关键监控项。文档采用分类清单式结构,逐项列出指标含义与关注点,方便日常巡检时快速对照,也可作为监控体系搭建、告警阈值设置及性能调优的初始参考。资源共1个doc文件,整体大小286KB,内容以结构化条目为主,适合直接查阅或导入笔记工具二次整理,目前已有83人学习下载。对于正在规划数据库监控方案或需要统一指标口径的团队,这份文档能节省检索与筛选资料的时间,同时补全容易忽略的细节指标,比如缓冲池命中率、事务日志空间、死锁信息、进程内存利用率、页面读写速率等,有助于更早识别性能隐患、合理分配资源,并提升数据库整体可用性。文档内容具有一定系统性,既适合刚接触监控的新手梳理概念,也适合有经验的管理员对照查漏补缺。
1. 数据库监测指标:一份文档如何把「凌晨被叫起来看数据库」变成白天十分钟的事
凌晨两点被电话叫醒,说业务系统卡死,你登录数据库一看:连接数打满,慢 SQL 堆积,磁盘空间只剩 3%。这种场景大多数 DBA 和运维都经历过。如果手头有一份结构化的数据库监测指标文档,把该看什么、阈值设多少、怎么快速定位写清楚,你甚至不用起床——先让监控脚本把关键指标抓出来,判断是连接风暴还是锁等待,再决定要不要远程处理。「数据库监测指标」这份文档解决的不是「监控工具怎么装」,而是「监控体系怎么定」:从操作系统层到数据库实例层,再到业务会话层,一共十几个核心指标,按重要性分级,配好采集频率和报警阈值。适合三类人:刚接手数据库运维的开发兼运维、准备做数据库巡检制度的企业内部团队、以及想把自己的踩坑经验固化成标准化文档的工程师。这文章就按这个方向,从指标拆解、采集命令、阈值设定到避坑经验,把一套能落地的方案讲清楚。
2. 把监测指标拆成可落地的三层结构:采集层、指标层、阈值层
一份合格的数据库监测指标文档,从来不是简单堆指标。我见过很多团队的监控文档,Excel 里列了几百个指标,真到用的时候没人知道先看哪个。按我做过的方案,核心是先把指标拆成三层结构:采集层定义「从哪里拿数据」,指标层定义「拿什么数据」,阈值层定义「拿到数据后怎么判断要不要报警」。
2.1 采集层:每个指标从哪里拿,用什么命令拿
采集层的核心是「数据源映射」。数据库监测指标的第一道坎,是搞清楚每个指标的出处。常见做法是这样:
- 操作系统层:用
top、iostat、df -h拿 CPU、IO、磁盘数据; - 数据库实例层:通过数据库自带的状态视图拿,比如 MySQL 的
SHOW GLOBAL STATUS、Oracle 的V$SYSSTAT、PostgreSQL 的pg_stat_database; - 业务会话层:通过
information_schema.processlist或者V$SESSION拿当前连接、活跃事务、锁等待。
对每个指标,文档里都应当写成这样一张「指标—来源—命令」对照表:
| 指标 | 来源 | 采集命令(MySQL 为例) | 优先级 |
|---|---|---|---|
| 连接数使用率 | 实例状态 | SHOW GLOBAL STATUS LIKE 'Threads_connected'; | P0 |
| CPU/IO 负载 | 操作系统 | top -bn1 | head -20 | P0 |
| 慢查询数 | 实例状态 | SHOW GLOBAL STATUS LIKE 'Slow_queries'; | P0 |
| 锁等待次数 | 实例状态 | SHOW GLOBAL STATUS LIKE 'Table_locks_waited'; | P1 |
| 磁盘剩余空间 | 操作系统 | df -h /var/lib/mysql | P0 |
这张表的逻辑来自我的一个原则采集层只放「一条命令能拿到的指标」。如果某个指标要写 20 行 SQL 才能查出来,它就不应该出现在日常巡检里,而是放到专项诊断文档里。
2.2 指标层:P0/P1/P2 分级,不谈权重谈优先级
指标层最常犯的错误是「贪多求全」。我见过一份监测指标文档,光 MySQL 就列了 80 个状态变量,结果巡检的人从上班看到下班都看不完,最后所有指标都不看了。所以要把指标分级,每个指标只保留「出问题时能直接指出故障方向」的字段。
P0 级指标,故障发生时第一时间要看,缺一个都不行:
- 连接数使用率(是否接近 max_connections 上限)
- QPS/TPS 变化趋势(业务是否异常波动)
- 慢查询数量与平均耗时(SQL 性能是否劣化)
- 磁盘剩余空间(写满后数据库直接只读或宕机)
- CPU/IO 平均负载(硬件资源是否打满)
P1 级指标,日常巡检必看,但不做实时报警:
- 锁等待次数与平均等待时长
- 缓存命中率(InnoDB Buffer Pool)
- 主从复制延迟(从库读延迟是否影响业务)
- 活跃会话数与会话等待事件分布
P2 级指标,留着做趋势分析,不为它设报警:
- 单条慢 SQL 的具体执行计划
- 历史上某一天的 QPS 峰值对比
- 数据库缓冲池碎片率、表空间碎片率
我一般会在指标层的末尾加一句话,如果你只能盯五个指标,就盯 P0 那五个。这句话看着没技术含量,但真能救命。
2.3 阈值层:阈值怎么设才不误报不漏报
阈值层的价值,在于把「感觉不对劲」变成「数字超过 80 就该响」。一个阈值定得太死,天天误报,最后报警被当成噪音;定得太松,真出事还没触发。我踩过的坑告诉我,阈值设定只有三个原则:按资源类型区分、按业务周期调整、按故障影响倒推。
先给一个我常用的初始阈值表,注意它只是起点:
| 指标 | 阈值(默认) | 说明 |
|---|---|---|
| 连接数使用率 | 80% 警告,95% 严重 | 超过 80% 说明连接池可能出现堆积 |
| CPU 平均负载 | 核数 x 0.7 警告 | 单核机器 load 超 1 就该查了 |
| 磁盘剩余空间 | 小于 20% 警告,小于 10% 严重 | 别等 5% 再报警,清理都来不及 |
| 主从复制延迟 | 大于 10 秒警告,大于 60 秒严重 | 超过 60 秒业务基本读不到实时数据 |
| 慢查询数 | 5 分钟内超过 50 条警告 | 结合业务量调整 |
阈值设定有个实操技巧:不要直接设一个固定值,而是用「基线 + 浮动」的方式去设,这一部分在第 4 章总线里详细展开。这里只强调一个避坑点——阈值一定要区分「趋势性指标」和「瞬时性指标」。比如慢查询数,单次超过 50 条可能是偶然,但持续 5 分钟都超过 50 条就一定是 SQL 出现了退化,这种阈值看的是持续时长而不是瞬时值。
3. 不同数据库的监测指标差异:一份文档如何兼容 Oracle、MySQL、PostgreSQL 与国产库
为什么很多数据库监测指标文档写着写着就变成了 MySQL 专属文档?因为不同数据库的指标采集方式差异确实大。但文档的定位是「一套体系适配多个库」,所以指标层的字段要能对上不同数据库的等价对象。这一章的重点就是把「等价对象映射」讲清楚。
3.1 四大类数据库的指标等价表:会话、状态、慢日志、缓存
我常用的做法是建立一张「指标等价表」,字段在所有库里都有对应物,只是名字和获取方式不同。比如下面这四类核心指标。
连接信息在 MySQL 里看Threads_connected,在 Oracle 里看V$SESSION里STATUS='ACTIVE'的数量,在 PostgreSQL 里看pg_stat_activity的state='active'行数,在达梦数据库里看V$SESSIONS的STATE='ACTIVE'。慢 SQL 在 MySQL 里直接开 slow_query_log,Oracle 靠V$SQLAREA按ELAPSED_TIME排序,PostgreSQL 要装 pg_stat_statements 插件,达梦在V$LONG_SQL里查。缓存命中率,MySQL 是Innodb_buffer_pool_read_requests / Innodb_buffer_pool_reads,Oracle 是Buffer Cache Hit Ratio,PostgreSQL 是blks_hit / (blks_hit + blks_read),达梦看V$CACHE里的命中率字段。
把这套等价表写进文档里,核心价值是让执行巡检的人不需要同时精通四种数据库,只需要按表里对应关系一条条查就行。之前我在一个项目里带了 RAC 环境迁移,Oracle、MySQL、达梦三套库同时跑,就是靠这张表让新人上路第一天就能把主要指标采集齐。
3.2 用 SQL 查指标:以 Oracle 和达梦为例的采集语句
等价表建立后,还需要给每个库写具体的采集 SQL。这里说两个容易翻车的点。
第一个是 Oracle 查活动会话。很多人直接SELECT COUNT(*) FROM V$SESSION WHERE STATUS='ACTIVE',但这么做忽略了一个事实:你自己这个是连接,查出来的数字永远是大于实际业务会话数的。更准确的做法是:
SELECT COUNT(*) AS active_sessions FROM v$session WHERE status = 'ACTIVE' AND username IS NOT NULL AND type = 'USER';这段 SQL 的逻辑是过滤掉后台系统进程,只统计用户会话。其中username IS NOT NULL排除了 SYS 后台任务,type = 'USER'排除了数据库内部的后台进程队列。实际执行时你会发现两个库的计数差异经常超过 50%,就是因为漏了这两个过滤条件。
第二个是达梦数据库查慢 SQL。达梦的V$LONG_SQL是动态视图,不同版本字段名稍有改动,但核心的用法一致:
SELECT S.SQL_TEXT, S.ELAPSED_TIME, S.EXEC_SERIAL_NUMBER FROM V$LONG_SQL S ORDER BY S.ELAPSED_TIME DESC LIMIT 20;这段 SQL 把耗时最长的 20 条 SQL 拉出来。ELAPSED_TIME单位通常为毫秒,如果字段名在某一版本被改成TOTAL_EXEC_TIME,直接去看达梦自带的系统表V$SQL_TEXT做关联就可以。这个场景说明文档里的采集语句不能写得「只有一种写法」,要备注版本差异。
3.3 各数据库的特殊指标:不能跨库等价的那部分
有些指标做不了等价表,是某个库独有的,监测文档必须单列。比如 MySQL 的Innodb_row_lock_current_waits(当前行锁等待数)和Innodb_deadlocks(死锁累计次数),Oracle 的V$RESOURCE_LIMIT里的PROCESSES和SESSIONS上限,PostgreSQL 的pg_stat_replication中pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)做主从延迟计算,达梦的V$CACHE里的脏页数量和检查点状态。
这类特殊指标最大的价值是定位「只有这个库才会出的问题」。比如 Oracle 的V$RESOURCE_LIMIT显示 PROCESSES 接近上限时,业务会出现间歇性连接失败但应用日志没有任何报错;再比如 MySQL 的Innodb_deadlocks数值增长突然加速,大概率是程序里出现了事务交叉更新同一张表的场景。这些指标不能拿 MySQL 的经验去套 Oracle,文档里分开写是对的。
4. 把指标文档变成自动化巡检:定时采集 + 基线比较 + 报警触发的落地脚本
文档写得再细,如果采集靠人肉一条条命令去敲,执行几天就废了。所以数据库监测指标文档的落地,最后一定要变成一套能定时跑的脚本。这一章的方案我用 Python 实现了多库的采集和基线判断,用 Shell + SQL 轮询做轻量版采集,两套方案都验证过,任选一套即可。
4.1 Python 采集脚本:从 MySQL 抓指标并按阈值报警
下面是最小可用的脚本,连接 MySQL 抓 P0 指标,把结果写入日志并判断阈值。你要跑 Oracle、达梦,换连接串和 SQL 即可,框架共用。
import pymysql import datetime # 连接配置 conn = pymysql.connect( host="127.0.0.1", port=3306, user="monitor", password="your_pass", database="information_schema" ) cursor = conn.cursor() # 1. 连接数使用率 cursor.execute("SHOW GLOBAL STATUS LIKE 'Threads_connected'") threads_connected = int(cursor.fetchone()[1]) cursor.execute("SHOW VARIABLES LIKE 'max_connections'") max_connections = int(cursor.fetchone()[1]) conn_ratio = round(threads_connected / max_connections * 100, 2) # 2. 慢查询数(最近 5 分钟增量,依赖定期清零或取累计差值) cursor.execute("SHOW GLOBAL STATUS LIKE 'Slow_queries'") slow_queries = int(cursor.fetchone()[1]) # 3. 磁盘剩余空间(独立用 os 模块获取) import shutil disk_usage = shutil.disk_usage("/var/lib/mysql") disk_ratio = round(disk_usage.used / disk_usage.total * 100, 2) # 报告生成 now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") report = ( f"[{now}] active_conn={threads_connected}/{max_connections} " f"conn_ratio={conn_ratio}% slow_queries={slow_queries} " f"disk_used={disk_ratio}%\n" ) with open("/var/log/db_monitor.log", "a") as f: f.write(report) # 阈值判断,触发则写入报警文件 alerts = [] if conn_ratio > 80: alerts.append(f"连接数使用率 {conn_ratio}% 超过 80%") if disk_ratio > 85: alerts.append(f"磁盘使用率 {disk_ratio}% 超过 85%") if alerts: with open("/var/log/db_monitor.alerts", "a") as f: f.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + "|".join(alerts) + "\n") cursor.close() conn.close()代码的逻辑说明:先连接 information_schema,通过SHOW GLOBAL STATUS拿当前连接数和max_connections算出使用率,再拿慢查询累计值,磁盘直接用 Python 的shutil.disk_usage拿。三个指标拿完后拼接成一行文本追加到日志,如果某个指标超过阈值,把报警内容单独写到 alerts 文件方便后续接企业微信或短信通知。
参数说明:max_connections是数据库上限,生产环境通常 200~1000,比例超过 80% 要留意连接池泄漏;/var/lib/mysql是 MySQL 的数据目录,如果你的库在其路径,替换成真实挂载点;磁盘使用率 85% 是保守阈值,追求稳定的系统可设 80%,如果磁盘够大但业务写入频繁,设到 90% 还没事,但必须在 90% 时主动做清理预案。
4.2 Shell + SQL 轮询:不装任何客户端依赖的轻量采集方案
如果环境里 Python 都没有,或者运维规范不允许装额外依赖,那就用 Shell 直接调 mysql 客户端,生产机器基本都有。
#!/bin/bash # 轻量巡检:连接数 / 慢查询 / 磁盘 MYSQL="/usr/bin/mysql" DB_USER="monitor" DB_PASS="your_pass" HOST="127.0.0.1" # 采集连接数 CONN=$($MYSQL -h$HOST -u$DB_USER -p$DB_PASS \ -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'" 2>/dev/null | tail -1 | awk '{print $2}') # 采集慢查询累计值 SLOW=$($MYSQL -h$HOST -u$DB_USER -p$DB_PASS \ -e "SHOW GLOBAL STATUS LIKE 'Slow_queries'" 2>/dev/null | tail -1 | awk '{print $2}') # 磁盘使用率 DISK=$(df / | tail -1 | awk '{print $5}' | sed 's/%//') # 判断阈值 if [ "$CONN" -gt 200 ] || [ "$DISK" -gt 85 ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') ALERT conn=$CONN slow=$SLOW disk=$DISK%" # 可以接 curl 调用企业微信机器人或短信平台 fi逻辑说明:用 mysql 命令带-e直接执行,tail -1取结果行,awk拿第二列数值。磁盘用df /取根分区使用率。
参数说明:这里的CONN -gt 200直接写死了连接数绝对阈值,适合固定并发规模的小系统;如果连接数基线在 600 左右,这个阈值应该改成 480 或 540。慢查询数在轻量版里只打日志不做阈值,原因是慢查询的波动范围太大,更适合用下面说的「基线偏移」来判断。
4.3 设置定时任务和基线:阈值不是死的,是跑出来的
脚本写好了,用 crontab 挂起来,每 1 分钟跑一次连接数,每 5 分钟跑一次慢查询。
# 编辑 crontab */1 * * * * /opt/scripts/db_monitor_conn.sh >/dev/null 2>&1 */5 * * * * /opt/scripts/db_monitor_slow.sh >/dev/null 2>&1两个不同频率的任务分开跑,连接数要盯得紧,所以它频率高;慢查询看趋势,频率低了减少库自身开销。这个逻辑适用于大多数业务。
基线判断的基本方法是一张历史表里存最近 7 天同一时段的指标值,当天实时值偏离基线超过 30% 就报警。比如昨天上午 10 点的连接数基数是 250,今天同一时刻到 400,即使离阈值还有距离也要引起警惕,这种「无征兆的上升」往往比阈值报警更早暴露问题。基线初始可以从文档的阈值表借数,跑两周后回填成实际分布区间,此后阈值建议只保留极端警戒,日常告警全交给基线偏移判断。
5. 避坑与排查:数据库监测指标落地的 5 个常见问题
指标文档写得漂亮、脚本也能跑,实际运行起来还是会踩坑。这几年我在数据库监测指标落地上遇到过的问题,集中在下面 5 个。每条都按「现象 → 原因 → 解决」来写,希望能让你少走弯路。
5.1 监控指标太多导致巡检走过场,报警被当噪音
现象:监控列表里两百多项指标,每一项都配了阈值,结果管理人员对报警逐渐麻木,真出问题时报警响了一小时没人处理,最后业务挂了才有人注意到。 原因:指标文档「大而全」但缺少分级,报警阈值有大量误报。比如内存使用率设成 90% 告警,但系统本身内存占用长期在 88%~92% 波动,每天报警几十次,久而久之所有人默认忽略。 解决:砍指标,只保留 P0 级 5~7 个,P1 级 10 个以内;阈值必须带上时间维度——持续 3 分钟超过才算 warning,持续 10 分钟才算 critical。我一般会在文档里写一行「报警噪音 = 最高级别事故的隐形凶手」,并严格执行 24 小时内不收敛的告警自动升级给二线处理。
5.2 慢 SQL 抓到了但不会分析,指标有数据却没结论
现象:慢查询日志里每天上千条记录,但团队只看数量,不看具体 SQL 内容,数据库还是会周期性抖动。 原因:监测文档把慢 SQL 数量写成了核心指标,却没说清楚「拿到记录后要做什么」。一个慢 SQL 被记录可能是索引失效、统计信息过期、数据量突增、争抢热行锁,甚至只是因为当时 buffer pool 被大查询挤占,只盯数量无法定位。 解决:慢查询相关监测要连抓三层——先看总量趋势,再按执行时间倒序取 TOP 20,最后对 TOP 20 逐条做执行计划解读。遇到数据量突增但 SQL 没变的场景,先查表统计信息和索引基数,再决定是否重建统计信息或改写 SQL。
5.3 不同数据库的采集脚本混用,导致指标数据不可比
现象:同一天 Oracle 库报活动会话 120 个,MySQL 报连接数 100 个,管理层拿两个数字对比,得出「MySQL 比 Oracle 负载低」的错误结论。 原因:Oracle 的活动会话统计了所有非空闲的用户会话,MySQL 的连接数是包含空闲连接的,两者根本不是一回事。采集脚本没有在指标字段上标明口径,导致跨库对比失效。 解决:在监测指标文档开头加一页「指标口径说明」,每个指标标注它的定义边界。比如 MySQL 的Threads_connected包括 Sleep 状态连接,在分析高连接数问题时要结合SHOW PROCESSLIST里 State 的分布;Oracle 的V$SESSION要过滤TYPE='USER'。跨库对比只能比趋势,不能比绝对值,这个结论也直接写进了文档的注意事项。
5.4 监控脚本自身成为故障源:高频率采集拖垮生产库
现象:上了监控后,某台老库的性能比之前更差,排查发现监控脚本每 10 秒执行一次SHOW FULL PROCESSLIST,大量查询堆积,占满了数据库连接池。 原因:采集频率太密,监控查询本身变成了 SQL 压力来源。尤其是information_schema下的一些视图查询,会在库内部产生大量临时表操作。 解决:区分「实时监控」和「离线巡检」两类采集。实时监控只跑轻量的SHOW GLOBAL STATUS,频率下限为 1 分钟;离线巡检跑processlist、pg_stat_activity这类重查询,频率放到 5 分钟甚至 10 分钟一次。监控账号的max_connections单独留 5 个连接,避免和业务抢连接。
5.5 磁盘和时区两个「非数据指标」反而造成大事故
现象:数据库表空间充足,但数据库突然进入只读模式,排查最后发现是 binlog 所在磁盘分区写满;另一个事故是监控报表的时区没对齐,报警时间比实际发生时间早了 8 小时,值班人现场排查时错过了关键窗口。 原因:监测指标文档里只写了数据库实例层的指标,没覆盖日志目录所在分区的磁盘空间;时区问题则更隐蔽,采集脚本用服务器本地时区入库,但分析端默认按 UTC 展示。 解决:磁盘监测按三个目录分别做——数据目录、日志目录、归档目录,任何一个超过 85% 就报警;时区统一在采集脚本里用 UTC 时间戳入库,展示层再转换成业务时区。这个坑不好发现,我上次差点为此背锅,后来在自己的文档模板里加了一行「所有时间字段存 UTC,永远不要在应用层改时区」。
6. 进阶用法:用监测指标做联动扩缩容与故障预测
数据库监测指标建立并稳定运行后,下一步不是继续加指标,而是把指标「用起来」。我用得最多的两个场景:一是连接池联动扩缩容,二是把历史指标变成故障预测基线。
连接池联动是目前最实用的自动化场景。当监测脚本发现conn_ratio连续 5 分钟超过 80% 且 QPS 同步上升,自动对应用层连接池执行扩容指令;当conn_ratio回落到 40% 以下并稳定 15 分钟,缩容回收。实现上只需在报警文件里追加一个动作字段,由发布系统读取后调连接池 API。这个循环不能完全替代人,但能把 80% 的连接风暴消灭在用户感知之前。
故障预测则依赖第 4 章建立的基线表。我会把每次故障发生前 30 分钟的指标快照和历史正常时段做对比,找出什么样的组合特征是故障前兆。比如某系统故障前 30 分钟的典型特征是「活跃会话数陡增 50% 以上 + 锁等待时间增长 3 倍 + 慢查询数同步上升」,这三个指标同时出现时,故障命中率超过八成。之后把这组条件写进监测脚本作为「预警模式」,提前 10 分钟通知到人。刚开始做会频繁误报,但每经历一次真实故障就调整一次规则,半年后准确率能到可接受的范围。
我从第一次做数据库监测指标文档到现在,最大的教训是:文档的最终交付物不是一份写满指标的 Word 文件,而是「人在看它之前,系统已经替人把 90% 的异常筛过一遍」的那套机制。指标永远在精不在多,阈值永远要跟着实际业务跑出来而不是抄默认值。希望这套思路能帮你在自己的环境里把数据库监测真正落地成一件「没感觉但一直在线」的事,希望帮到你。
本文还有配套的精品资源,点击获取