@ashrpt.sql无法查到秒级抖动,因其硬编码最小粒度为5分钟,输入60秒会被强制调整为300秒并报ora-13773;定位亚分钟抖动必须直查v$active_session_history,用sample_time精确过滤并秒级分组聚合。
不能靠 @ashrpt.sql 查到秒级抖动——它硬编码最小粒度为 5 分钟,传入 60 秒也会被自动调整为 300 秒,报 ora-13773;真要定位几十秒内的尖峰,必须直查 v$active_session_history,用 sample_time 精确过滤 + 秒级分组聚合。
为什么 @ashrpt.sql 查不到 1 分钟内的抖动?
这不是配置错、权限缺或采样关了,是 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 - 查 30 秒级热点(避免跨分钟平均掩盖峰值):
TRUNC(sample_time, 'SS') + FLOOR(TO_NUMBER(TO_CHAR(sample_time, 'SS'))/30)*30/86400 - 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或SQL_PLAN_HASH_VALUE关联历史执行计划
容易被忽略的采样偏差和时区问题
ASH 是概率采样,不是每秒 100% 连续捕获。10ms 等待事件被采样的概率远低于 100ms 事件,所以短时高频等待可能漏掉;SAMPLE_TIME 是数据库时区时间,不是系统时区,也不一定是 UTC——如果你用应用日志里的时间戳去查,没转换时区就直接套用,很可能查空。
最稳妥的做法:用 SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE 这类动态条件,而不是写死字符串;抖动发生在 13:22:18,建议查 BETWEEN '13:22:03' AND '13:22:53',留出 ±15 秒余量。











