@ashrpt.sql无法查到秒级抖动,因其硬编码最小粒度为5分钟,输入60秒会被强制调整为300秒并报ORA-13773;定位亚分钟抖动必须直查v$active_session_history,用SAMPLE_TIME精确过滤并秒级分组聚合。

查不到秒级抖动,不是你时间输错了,是 @ashrpt.sql 本身就不支持亚分钟粒度——它硬编码最小 duration 为 300 秒,输 60 秒也会被强制改成 300 秒并报 ORA-13773。
为什么 @ashrpt.sql 查不出几十秒的尖峰
这不是权限缺、采样关或配置错,而是 Oracle 底层设计决定的:DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_TEXT 函数强制校验 duration >= 300。你输 duration => 60,日志里会明确写 “Duration adjusted to 300 seconds”。AWR 报告本质是对每秒一次的原始 ASH 记录做 5 分钟桶聚合,亚分钟细节必然被平滑掉。
常见错误现象:
- 监控看到 14:23:18–14:23:42 响应突增,但
@ashrpt.sql报告覆盖的是 14:20–14:25,CPU 平均仅 12% - 执行脚本时输入
begin_time=14:23、duration=60,结果报告时间范围变成 14:20–14:25,且提示 “Time range adjusted”
用 v$active_session_history 直查秒级抖动
关键不是“扫全表”,而是精准切片 + 秒级分组。先确认数据还在内存(默认保留约 1 小时),再用动态条件过滤:
- 查最近 2 分钟是否有采样:
SELECT COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 2/1440 - 避免跨分钟平均掩盖峰值:用
TRUNC(sample_time, 'SS') + FLOOR(TO_NUMBER(TO_CHAR(sample_time, 'SS'))/30)*30/86400实现 30 秒分组 - RAC 环境必须用
gv$active_session_history,否则只看到当前节点 - 别只筛
event,加session_state = 'WAITING'或'ON CPU'联合过滤,快速区分是等资源还是真在跑
从高频 event 往下挖根因
event 是入口,但单看它不够。真正要盯的是三列:blocking_session、sql_id、p1text/p1:
-
enq: TX - row lock contention→ 立刻查对应blocking_session的sql_id和执行计划,大概率是未提交事务锁了热点行 - 大量
db file sequential read且current_obj#相同 → 某张小表被反复单块读,可能是索引失效或绑定变量窥探失准 -
latch: cache buffers chains不一定缺索引 → 得结合p1(file#) 和p2(block#) 定位热块对象,再看 B-Tree 结构是否倾斜 -
v$SQL可能查不到 SQL 文本(已老化出共享池)→ 此时得用DBA_HIST_SQLTEXT或直接从gv$active_session_history的sql_text字段捞(如果启用了采集)
容易被忽略的 RAC 和时区细节
RAC 下漏查 blocking_instance、跨节点阻塞没关联上,或者 sample_time 用错时区,都会让抖动定位完全偏航:
- 查
v$session时,RAC 必须加AND blocking_instance = instance_number,否则可能漏掉跨实例阻塞 - 查
dba_hist_active_sess_history时,sample_time条件务必用数据库所在时区,比如WHERE sample_time BETWEEN TIMESTAMP '2026-07-21 14:23:00' AND TIMESTAMP '2026-07-21 14:23:45' -
CONNECT BY构建阻塞链时,必须加sample_id = PRIOR sample_id - 1(不是相等),否则会把不同时刻的会话强行连起来 -
blocking_session为 0 或空,说明它是根阻塞者;若同一sql_id在多个sample_id中反复出现,优先检查它的事务是否未提交



















