字典缓存命中率低于95%且伴随row cache latch等待飙升、library cache reloads暴增或shared pool空闲内存持续低于50mb,表明解析链雪崩;应查v$rowcache实时命中率及明细,重点关注dc_users、dc_objects等高miss项,根源多为应用频繁身份校验或元数据查询,而非shared_pool_size不足。

Dictionary Cache Stats 这部分数据不是“看看就行”的装饰项,而是字典缓存压力的直接体温计。命中率低于 95% 本身不构成问题,但若伴随 latch: row cache objects 等待飙升、library cache reloads 暴增或 shared pool free memory 持续低于 50MB,则说明解析链正在雪崩。
怎么看 Dictionary Cache Hit Ratio 是否真异常
别只信 AWR 报告里那个静态百分比——它只是两个快照间的 delta 值,可能掩盖尖峰。直接查当前实时值更可靠:
SELECT (1 - SUM(getmisses)/NULLIF(SUM(gets),0)) * 100 AS "Row Cache Hit Ratio" FROM v$rowcache;
- 结果稳定在 98%+,基本可排除字典缓存层瓶颈
- 若低于 95%,立刻往下钻
v$rowcache的明细:重点关注getmisses高的项,尤其是dc_objects、dc_users、dc_segments、dc_sequences - 注意趋势:某次部署后从 99.2% → 87.3%,且
latch: row cache objects平均等待时间同步翻倍,这才是关键信号
dc_users 和 dc_objects miss 高,先查应用连接和 SQL 行为
这两类 miss 高,90% 以上不是 shared_pool_size 不够,而是应用在“反复验证身份”或“反复查对象是否存在”。
-
dc_usersmiss 高:检查是否大量不同用户名直连(如未启用连接池),或存在硬编码ALTER SESSION SET CURRENT_SCHEMA=...,每次执行都触发用户权限校验 -
dc_objectsmiss 高:运行以下语句抓高频元数据查询 SQL:
SELECT sql_id, sql_text FROM v$sql WHERE sql_text LIKE '%dba_%' OR sql_text LIKE '%all_%' OR sql_text LIKE '%v$%';
- 常见元凶:监控脚本每 5 秒刷一次
DBA_OBJECTS;开发写的 PL/SQL 块用SELECT COUNT(1) FROM all_tables WHERE table_name = 'T'判断表是否存在;GUI 工具自动展开对象树 - Oracle 19c+ 中,若启用了
optimizer_adaptive_features,某些自适应统计收集也会密集访问dc_users和dc_objects
row cache lock 等待高,别急着加 shared_pool_size
row cache lock 是保护字典缓存结构的串行化锁,争用高 ≠ 缓存小,更可能是“高频短操作”打在同一把 latch 上。
- 先确认是否真是该等待主导:查
v$system_event中latch: row cache objects的time_waited_micro占比 - 若 P1 值对应
dc_sequences(查v$rowcache的cache#):序列没设CACHE是主因,补上ALTER SEQUENCE seq_name CACHE 20; - 若 P1 对应
dc_users:查DBA_AUDIT_TRAIL中返回码1017(密码错)或1005(空密码)的登录失败记录,很可能是暴力探测或配置错误导致的认证风暴 - 调大
shared_pool_size对上述两类问题基本无效——因为不是内存不足,而是 latch 获取路径太热
shared_pool 碎片化比 free memory 少更危险
AWR 里显示 Shared Pool Free % 是 78%,不代表健康。19c 的 ASMM 下,真正要命的是“大块内存找不到”。
- 运行:
SELECT bytes, count(*) FROM v$sgastat WHERE pool = 'shared pool' GROUP BY bytes ORDER BY bytes DESC,看是否大量 - 对比
v$shared_pool_advice:如果建议的shared_pool_size明显大于当前值,说明碎片已影响新 SQL parse heap 分配 - 碎片诱因常被忽略:频繁 DDL(如每分钟建/删临时表)、
ENABLE_DDL_LOGGING=TRUE但日志表未分区(导致dc_logstdby反复失效)
最易被跳过的环节是:没确认 v$sgastat 中 row cache 自身占用是否稳定(通常就几 MB),就直接去调 shared_pool —— 这相当于给空调加氟前,没查是不是窗户开着。











