首页 / 资讯中心 / 文章详情

数据库监测指标落地指南:三层拆解、多库兼容与自动化巡检方案

数据库监测指标落地指南:三层拆解、多库兼容与自动化巡检方案 ★ FEATURED ARTICLE
简介面向数据库管理员与运维人员的监测指标参考文档集中梳理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;P0CPU/IO 负载操作系统top -bn1 | head -20P0慢查询数实例状态SHOW GLOBAL STATUS LIKE Slow_queries;P0锁等待次数实例状态SHOW GLOBAL STATUS LIKE Table_locks_waited;P1磁盘剩余空间操作系统df -h /var/lib/mysqlP0这张表的逻辑来自我的一个原则采集层只放「一条命令能拿到的指标」。如果某个指标要写 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里STATUSACTIVE的数量在 PostgreSQL 里看pg_stat_activity的stateactive行数在达梦数据库里看V$SESSIONS的STATEACTIVE。慢 SQL 在 MySQL 里直接开 slow_query_logOracle 靠V$SQLAREA按ELAPSED_TIME排序PostgreSQL 要装 pg_stat_statements 插件达梦在V$LONG_SQL里查。缓存命中率MySQL 是Innodb_buffer_pool_read_requests / Innodb_buffer_pool_readsOracle 是Buffer Cache Hit RatioPostgreSQL 是blks_hit / (blks_hit blks_read)达梦看V$CACHE里的命中率字段。把这套等价表写进文档里核心价值是让执行巡检的人不需要同时精通四种数据库只需要按表里对应关系一条条查就行。之前我在一个项目里带了 RAC 环境迁移Oracle、MySQL、达梦三套库同时跑就是靠这张表让新人上路第一天就能把主要指标采集齐。3.2 用 SQL 查指标以 Oracle 和达梦为例的采集语句等价表建立后还需要给每个库写具体的采集 SQL。这里说两个容易翻车的点。第一个是 Oracle 查活动会话。很多人直接SELECT COUNT(*) FROM V$SESSION WHERE STATUSACTIVE但这么做忽略了一个事实你自己这个是连接查出来的数字永远是大于实际业务会话数的。更准确的做法是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( host127.0.0.1, port3306, usermonitor, passwordyour_pass, databaseinformation_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} fconn_ratio{conn_ratio}% slow_queries{slow_queries} fdisk_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_USERmonitor DB_PASSyour_pass HOST127.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 21 */5 * * * * /opt/scripts/db_monitor_slow.sh /dev/null 21两个不同频率的任务分开跑连接数要盯得紧所以它频率高慢查询看趋势频率低了减少库自身开销。这个逻辑适用于大多数业务。基线判断的基本方法是一张历史表里存最近 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要过滤TYPEUSER。跨库对比只能比趋势不能比绝对值这个结论也直接写进了文档的注意事项。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% 的异常筛过一遍」的那套机制。指标永远在精不在多阈值永远要跟着实际业务跑出来而不是抄默认值。希望这套思路能帮你在自己的环境里把数据库监测真正落地成一件「没感觉但一直在线」的事希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站