必须直查v$active_session_history(rac用gv$)定位秒级卡顿点,因其每秒采样非空闲会话并记录sql_id、event、blocking_session、sample_time等字段构成“卡顿快照”,而ash报告是聚合摘要会抹平瞬时卡顿;需加sample_time > sysdate - interval '5' minute过滤,结合连续多秒同一sql_id+同一event的证据链,并对齐to_char(sample_time, 'hh24:mi:ss')到秒级精度。

直接查 v$active_session_history,别等 ASH 报告
ASH 报告是聚合摘要,秒级卡顿会被抹平;真正定位“哪一秒卡住”,必须直查 v$active_session_history。它每秒采样一次非空闲会话(session_state != 'WAITING' 或等待具体事件),字段如 sql_id、event、blocking_session、sample_time 组合起来就是一张“卡顿快照”。
常见错误是只查 v$ 视图——RAC 环境下必须用 gv$active_session_history,否则漏掉其他节点的卡点。
- 加时间过滤:
SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE,ASH 内存默认只保留约 1 小时,高负载下可能更短,5 分钟足够捕获瞬时尖刺又避开噪声 - 别只盯
sql_id:同一sql_id可能对应多个sql_plan_hash_value,卡顿往往只发生在某个子游标上 -
sql_id为空时,重点看program、module和event:可能是 PL/SQL 匿名块、递归调用或硬解析风暴
session_state = 'ON CPU' 和高频 event 要分开看
“卡”不等于“等”,ON CPU 表示真正在执行,不是 I/O 或锁争用;而 event 字段才揭示等待类型。两者叠加才能判断瓶颈性质。
-
session_state = 'ON CPU'+ 长时间重复出现 → CPU 密集型 SQL,检查执行计划是否走了全表扫描或低效连接 -
event = 'db file sequential read'→ 单块读为主,大概率是索引查找、回表或小结果集排序 -
event = 'enq: TX - row lock contention'→ 行锁阻塞,配合blocking_session可直接定位持锁会话 -
event = 'row cache lock'或enq: US - contention'→ 共享池或 UNDO 段争用,典型根因是序列没设CACHE、UNDO 表空间不足
按 sql_id + event + 时间窗口聚合,找真实“卡顿证据链”
单条样本意义有限,连续多秒采样落在同一 sql_id + 同一 event 上,才是卡顿的强证据。不要依赖 AWR 的“Top SQL by DB Time”,它按累计值排序,可能掩盖只在 14:02:17–14:02:22 执行 5 次、每次 800ms 的致命 SQL。
- 用
TO_CHAR(sample_time, 'HH24:MI:SS')对齐到秒,观察是否密集连续采样 - 聚合示例:
SELECT sql_id, event, COUNT(*) cnt, MIN(sample_time), MAX(sample_time) FROM gv$active_session_history WHERE sample_time BETWEEN TIMESTAMP '2026-07-21 14:02:00' AND TIMESTAMP '2026-07-21 14:02:30' GROUP BY sql_id, event ORDER BY cnt DESC - 若发现某
sql_id在 3 秒内被采样 20+ 次且event为enq: TX - contention,基本可锁定为该 SQL 引发的行锁风暴
查到慢 sql_id 后,下一步必须看实际执行计划和绑定变量
ASH 告诉你“卡在哪”,但不解释“为什么卡”。同一个 sql_id 可能因绑定变量不同走完全不同执行计划——比如一个走索引,一个全表扫描。
- 用
DBMS_XPLAN.DISPLAY_CURSOR('xxx', NULL, 'ALLSTATS LAST')查当前执行的真实计划,关注Rows和Starts是否严重偏离预估 - 查
v$sql_bind_capture看历史绑定值,确认是否因谓词值分布倾斜导致计划选择错误 - 如果发现多个
sql_plan_hash_value,说明存在计划抖动,需考虑禁用绑定变量窥探或使用 SQL Plan Baseline 锁定稳定计划
最易被忽略的是:RAC 环境下 gv$ 查询未指定 inst_id 过滤,或未对齐到秒级时间戳就做聚合,会导致卡顿点被稀释或错位。











