
简介数据库监测是保障数据库高效、稳定运行的核心环节这份文档面向DBA、运维及性能调优人员系统梳理了Oracle、SQL Server、Sybase、Informix、DB2等主流数据库的关键监测指标。内容涵盖连接会话与事务处理、锁和死锁检测、缓冲池与Cache命中率、进程与内存利用率、表空间与日志空间管理、I/O读写速率、检查点与多线程调度等多个维度并对每类指标给出了具体监测参数例如游标数、Session数、每秒事务数、Largest Chunk、Transaction Log Size、Page Read/Write Rate、Dead-lock Rate等覆盖从操作系统交互到数据库内部结构的各层状态帮助读者从性能、资源、并发、存储等层面建立完整监控视图。资源包共1个文件为286KB的doc文档内容按数据库类型分模块呈现便于查阅和对照实践。已有83人学习/下载适合正在构建数据库监控方案、梳理性能调优知识体系或开展数据库巡检的运维人员参考使用。1. 数据库监测指标别靠背这份清单解决的是“该看什么”和“怎么看”做运维的前三年我桌上总摆着一本打印出来的指标手册Oracle、SQL Server、Sybase、Informix、DB2、MySQL的监控项密密麻麻排在一起。数据库监测指标这件事难的不是采集工具而是你不知道哪些指标真正反映问题。数据库监测指标清单这份文档就是把六类数据库的几百个监测项按库、按模块归好了类游标、Session、锁、缓冲池、表空间、网络读写、死锁信息全都有。它适合刚接手数据库监控的DBA也适合做监控平台的人拿来当字段字典。看完你就知道每个指标不是孤立数字而是背后对应一种故障模式。接下来我就按库拆开讲哪些指标值得每天看哪些是忽悠人的。2. 先啃 Oracle游标、Session、锁与缓冲池命中率的真实读法2.1 会话与游标判断连接是否健康的两个起点Oracle 指标里游标数和 Session 数排在前面这俩是一对。游标数是当前打开的游标总量Session 数是数据库当前的会话连接数。很多人一看 Session 数接近上限就慌其实要先分清是活跃会话还是空闲会话。常见做法是查v$session的status字段把 ACTIVE 和 INACTIVE 分开统计。SELECT status, COUNT(*) FROM v$session GROUP BY status; SELECT COUNT(*) AS total_cursors FROM v$open_cursor;第一句看会话状态分布第二句看全局打开的游标总数。如果 INACTIVE 的会话特别多问题多半出在应用层连接池没释放而不是数据库自身。游标数高的时候我更倾向于查v$sqlarea里open_versions很大的 SQL而不是直接清缓存。参数上要注意两点OPEN_CURSORS是单个会话能打开的游标上限默认值一般够用但应用用了大量 PreparedStatement 不关闭时会撞上。另一个是SESSIONS参数它受PROCESSES影响改的时候两个要一起调只改一个会在启动时报错。2.2 锁和死锁从数量倒推阻塞场景数据库锁数量和死锁数量是监测并发控制的核心指标。Oracle 里查锁最直接的是v$lock但v$lock是行级锁和对象锁的混合体直接数会混入很多 TM 锁。我一般用下面这个查询把锁按类型和模式分好SELECT l.type, l.mode, COUNT(*) lock_count, s.username, s.machine FROM v$lock l LEFT JOIN v$session s ON l.sid s.sid GROUP BY l.type, l.mode, s.username, s.machine ORDER BY lock_count DESC;锁数量多不一定就是问题要看阻塞链。实际排障时先用v$session找BLOCKING_SESSION再用v$session_wait看等待事件。有一种很常见的翻车现场死锁数量一直在涨但查v$lock没有锁因为死锁已经被 Oracle 自动回滚释了。所以死锁监测要用alert_log抓ORA-00060或者开启deadlock_detection跟踪不能只看实时锁数量。2.3 缓冲池命中率别再盯着 98% 不放了缓冲池命中率是最容易被误读的指标。文档里 Oracle 的 Cache 命中率和 Buffer 命中率都列了但同样的 99% 命中率在 OLTP 和 OLAP 场景下完全是两个意思。OLTP 大量短查询命中率低反而说明数据访问模式合理OLAP 全表扫描多命中率虚高只是因为扫描过的块还在内存里。我统计过一份生产库命中率 99.8%但 AWR 里physical read total I/O requests照样高因为吞吐大1% 的未命中就能产生大量物理读。想判断缓冲池是否够用我一般看v$db_cache_advice它会模拟不同db_cache_size下的物理读数量那个趋势线比命中率更直观。另外Largest Chunk指标反映的是共享池里最大的空闲内存块如果这个值越来越小并伴随ORA-04031说明共享池碎片化严重该考虑shared_pool_reserved_size或者改用大页。3. SQL Server 与 Sybase性能计数器里的“速率”陷阱3.1 SQL Server 的缓存与内存计数器怎么对应现实问题SQL Server 部分文档列了 Page Read Rate、Page Write Rate、Free Data Cache Buffers还有 SQL Memory Manager 下的一串内存计数器。这些指标有个共同点它们都是速率或者瞬时值单独看没有意义。比如 Page Read Rate 是每秒物理读页面数要对比的是磁盘能力而不是这条 SQL 本身。我看 SQL Server 的习惯是先看sys.dm_os_performance_counters里的关键计数器再对照sys.dm_os_wait_stats里的PAGEIOLATCH_SH等待。SELECT counter_name, cntr_value, CASE WHEN counter_name LIKE %(KB/sec)% OR counter_name LIKE %(number/sec)% THEN Rate ELSE Snapshot END AS counter_type FROM sys.dm_os_performance_counters WHERE object_name SQLServer:Buffer Manager AND counter_name IN (Buffer cache hit ratio, Page reads/sec, Page writes/sec);执行这段之前提醒一下Buffer cache hit ratio 的 cntr_value 是累计值不是百分比要看Buffer cache hit ratio base做除法。这是一个特别容易踩的坑很多监控平台的 SQL Server 命中率算出来超过 100%就是因为直接拿cntr_value当百分比用了。正确算法是ratio / base * 100。SQL Server 的Free Data Cache Buffers保持低位其实是正常状态缓存就是用来用的闲置太多反而说明内存分配过大了。真正要盯的是sys.dm_exec_query_stats里total_worker_time和total_elapsed_time的比值那能看出 CPU 消耗集中在哪里。3.2 Sybase 的 I/O 与网络包指标容易误读的一组Sybase 指标里有一串“每分钟”的计数器每分钟读取次数、写入次数、读取输入数据包数、写入输出数据包数、读写错误数还有服务器 CPU 时间和空闲时间。注意这里的时间单位是“每分钟”不是秒。所以拿到这些指标后第一件事就是确认采集间隔是不是 1 分钟否则算出来的速率是错的。Sybase 最常见的监测方式是sp_monitor它会输出一段文本里面有每秒 CPU 忙、IO 读写、包读写等数据但它是累计值两次执行之间的差值才是这段时间的变化。我习惯用一个脚本定时抓取两次再做差。-- 第一次执行记录当前累计值 exec sp_monitor go -- 等60秒后执行第二次 exec sp_monitor go看第二次输出时重点看packets read和packets written的增量。如果网络读包增加但写包不涨可能是客户端请求多但事务没有提交要配合sysprocesses查阻塞。Sybase 的死锁指标在文档里单独列出包括死锁数、最长死锁时间、死锁进程 ID这些信息靠sp_configure开启死锁报告才能拿到不然只有错误日志里有零散记录。3.3 一份可以直接抄的采集 SQL 模板无论是 SQL Server 还是 Sybase我都不建议手工一条条执行。下面这个 SQL Server 模板把缓冲池、连接和用户管理三类指标合并成一次查询可以直接丢到监控脚本里隔 60 秒跑一次。SELECT GETDATE() AS collect_time, (SELECT cntr_value FROM sys.dm_os_performance_counters WHERE object_name SQLServer:Buffer Manager AND counter_name Buffer cache hit ratio) * 1.0 / (SELECT NULLIF(cntr_value, 0) FROM sys.dm_os_performance_counters WHERE object_name SQLServer:Buffer Manager AND counter_name Buffer cache hit ratio base) AS hit_ratio, (SELECT cntr_value FROM sys.dm_os_performance_counters WHERE object_name SQLServer:General Statistics AND counter_name User Connections) AS user_conn, (SELECT cntr_value FROM sys.dm_os_performance_counters WHERE object_name SQLServer:Memory Manager AND counter_name Total Server Memory (KB)) AS total_mem_kb;这里NULLIF是用来防止 base 为 0 时除零的这个细节在很多生产环境里救过命。Total Server Memory是当前 SQL Server 持有的内存配合Maximum Server Memory看可以判断是不是内存压力过大持续接近上限说明要评估 max server memory 的设置了。4. Informix 与 DB2冷门库的指标反而最需要整理4.1 Informix 的空间与 checkpoint 指标Informix 在很多公司里是“老遗产”一般的存在文档里给的指标却最细逻辑日志文件总数、表总数、表所用页面总数、块空间总数、剩余空间还有 Server Mode、Check-point in progress、Page Size、Thread Spawn Rate、Virtual Processors 等。这些指标用一条onstat命令就能拿到一大半。onstat -g chunk onstat -g dsk onstat -c | grep checkpointonstat -g chunk查看每个 chunk 的空间分配与剩余量对应文档里的 Chunks、Space Allocated、Space Used、Space Utilization。onstat -g dsk看磁盘读写、排序溢出等速率指标。onstat -c输出的 checkpoint 配置里Check-point in progress如果长时间为 1说明检查点卡住了通常是刷脏页太慢要检查ONLILOGS目录所在的磁盘 I/O。Informix 的Logical Log Records Write Rate和Logical Log Pages Write Rate是累计速率两次采样差值才有意义。另外看Dead-lock Rate和Lock Wait Rate时要分清楚是每分钟还是每个事务文档里没写单位实际用onstat -p看到的是自启动以来的累计次数要除以运行秒数换算成速率。4.2 DB2 的连接、代理与缓存池状态DB2 指标分了三块连接状态、代理状态、缓存池状态。连接状态里的Current Connections是当前连接数Connection Rate是新连接建立速率如果两者都高且伴随Agents Waiting上涨说明并发连接超过了可用代理数量。DB2 的命令行工具db2pd比 SQL 查询更直接db2pd -db 数据库名 -agents db2pd -db 数据库名 -bufferpools db2pd -db 数据库名 -tcbstats-agents输出的Agents Waiting和ActiveAgents就能对上文档里的 Active Agents、Idle Agents、Agents Waiting。-bufferpools里有 Buffer Pool Hit Ratio、Index Page Hit Ratio、Data Page Hit Ratio注意 db2pd 的命中率已经是百分数不用再乘 100。-tcbstats看的是表缓存对应 Package Cache Hit Ratio 和 Catalog Cache Hit Ratio。DB2 有篇文章里常提“Direct Reads”和“Direct Writes”这是指绕过缓冲池直接读写的页数通常发生在LONG VARCHAR大字段或临时表空间。如果 Direct Reads 占物理读的比例超过 30%就要检查是不是有大字段操作没走缓冲池不能只看缓冲池命中率。4.3 用命令行工具拉取指标的工作习惯Informix 和 DB2 不像 Oracle、SQL Server 那样有统一视图所以我的习惯是把命令封装成脚本定时跑并把结果落到表里。比如 DB2 的采集脚本每次执行db2pd后把关键字段用awk抽出来再插入监控表。这样能把文档里的指标和历史对比。db2pd -db PROD -bufferpools | awk /Buffer Pool Hit Ratio/{print $NF} /var/lib/db2mon/bp_hit_ratio.log这条命令把命中率数值追加到日志文件配合 crontab 每 5 分钟一次就能画出趋势。要提醒的是db2pd的部分指标输出会因为授权级别不同而缺字段至少要SYSADM或SYSMON权限。Informix 的onstat同理需要informix用户执行onstat -g系列有些选项还要特定诊断模式。5. 数据库监测指标常见避坑为什么采集到的数据经常“对不上号”5.1 现象命中率 99% 但查询还是慢有一次给 Oracle 库做体检缓冲池命中率长期 99.8%但一个报表查询要跑 40 秒。一开始怀疑索引后来查v$segment_statistics才发现那个查询访问的表物理读在buffer busy waits里特别高。原因是命中率只覆盖了已访问的块而大量的小表扫描产生的逻辑读都被缓存了真正的物理读集中在几个热点块上。解决不要单看整体命中率要按对象拆查dba_segments里各段的物理读取次数找到真正拖后腿的表。5.2 现象死锁计数每天涨却不知道锁在哪某套 SQL Server 的Number of Deadlocks计数器一天涨到三位数但抓死锁图困难因为默认没开deadlock_trace。后来开启 1222 跟踪标记才看到是应用层先更新主表再更新明细表另一个进程顺序相反造成循环等待。解决所有数据库的死锁监测都要提前开启日志跟踪别等出事再开。Oracle 里设置events 10046 trace name context forever, level 8或简单点开deadlock_detectionSQL Server 用DBCC TRACEON(1222, -1)Sybase 靠sp_configure deadlock report打开。代价是少量性能损耗比裸奔强。5.3 现象表空间用了 80% 但文件没变大Oracle 的表空间使用率一直卡在 80%DBA 急着加文件我查了一眼发现是TEMPORARY表空间排序溢出导致临时段占用但临时段会在会话结束后自动释放。那个 80% 其实是峰值快照不是持续水位。解决看表空间使用率时先分清楚永久还是临时临时表空间要看v$sort_usage里的当前排序段而不是dba_tablespaces的分配总量。同理Sybase 和 Informix 的表空间“已用空间”如果包含逻辑日志也要单独拆出来。5.4 现象SQL Server 内存计数器一直在涨SQL Server:Memory Manager的Total Server Memory持续走高新手以为内存泄漏。实际是 SQL Server 默认用尽它认为合理的内存并缓存在 buffer pool 里。如果不想让它吃掉整个机器内存要在sp_configure里设置max server memory并预留内存给操作系统。完整设置方式用sp_configure show advanced options, 1后改max server memory重启服务生效。从那以后我遇到类似问题先看sys.dm_os_sys_memory判断是否物理内存不足而不是单看 SQL Server 自己的计数器。5.5 现象用快照差值算速率时出现负数数据库监测指标里的速率大部分是靠两次快照做差值再除以时间间隔得到的。有一次 Sybase 的sp_monitor二次采样后包写入速率算出来是 -2原因是对应的计数器发生了重置因为数据库重启过。解决采集脚本里要同时记录快照时间、服务器启动时间如果启动时间变了就要丢弃重启前后那一段数据。另外有的计数器是 64 位整型在高并发下翻转差值时会变成负数。我现在的习惯是差值计算前先做溢出判断如果这次值比上次小就按补码处理或者直接标记为无效点。6. 把监测指标从“看看”变成“能报警”基线阈值与趋势判断前面讲的都是怎么看单点指标但在生产环境里指标真正的价值是形成基线和趋势。比如 Oracle 的每秒事务数白天高峰 300凌晨 30如果你把报警阈值设成 200那凌晨必然误报。正确做法是先给每个指标算一周的分时段基线再按基线偏离度报警。我一般用一张表字段是指标名、实例、小时、平均、标准差每天跑一次汇总。INSERT INTO metric_baseline (metric_name, instance_name, hour_num, avg_value, stddev_value) SELECT transactions_per_sec, instance_name, TO_CHAR(sample_time, HH24), AVG(value), STDDEV(value) FROM metric_samples WHERE sample_day BETWEEN TRUNC(SYSDATE) - 7 AND TRUNC(SYSDATE) - 1 GROUP BY instance_name, TO_CHAR(sample_time, HH24);这个 SQL 是通用的换表名和字段就能用到任何数据库。有了基线后报警规则就是当前值与均值差超过 3 倍标准差时触发而不是固定阈值。这套方式比“死锁1 就报警”可靠得多死锁报警通常会从猎到漏报因为死锁频率和业务并发强相关。再一个技巧是把指标分成三层第一层黑匣子只看整体状态比如数据库状态、Listener 状态、连接数、表空间使用率适合做大屏第二层是问题定位比如死锁数、锁等待率、缓冲池命中率、Page Read Rate第三层是深度调优比如 Row Source Ratio、Sort Overflow Ratio、Chunk Wait Rate 这些小众指标只在做性能分析时看。日常监测只盯第一第二层第三层记在文档里出了问题再翻。我从做监控第一年就吃过这个亏把文档里所有指标都接进告警系统结果每天几百条通知没过两周就没人看了。后来我强制自己给每个指标写“这个数字异常意味着什么我该干什么”写不出来的就不接。这份指标清单的价值就在这里——它不是让你全接而是让你知道每种数据库有哪些牌可以打。我后来养成的习惯是每接手一个新数据库先对照这份文档的目录划掉用不上的专项指标再给剩下的每个指标配基线和阈值整个监控体系才真正转起来。希望帮到你。本文还有配套的精品资源点击获取