v$active_session_history是内存中每秒采样的原始数据源,非空闲会话状态(on cpu/waiting)、等待事件、sql_id及blocking_session等字段组合构成“卡顿快照”,需直查该视图并限定时间窗口(如sample_time > sysdate - interval '5' minute),rac环境须用gv$视图,才能准确定位秒级卡顿点。
v$active_session_history 本身不生成“ash报告”,它只是内存中每秒采样的原始数据源;所谓“ash报告”是 awrddrpt.sql 或 oem 等工具基于该视图聚合生成的摘要。能展示卡顿点,根本原因在于采样粒度和字段设计——不是它“知道卡在哪”,而是它在卡发生的那一秒,刚好拍下了会话的状态。
直接查 v$active_session_history 才是定位卡顿点的核心
你看到的“卡顿点”,其实是某条 SQL 在某个时间点被反复采样到处于非空闲状态(session_state != 'WAITING' 或等待特定事件)。比如:
-
session_state = 'ON CPU':说明那秒它真正在跑,不是等 I/O 或锁 -
event = 'db file sequential read':说明那秒它卡在单块读上,大概率是索引查找或回表 -
event = 'enq: TX - row lock contention':说明那秒它正堵在某行锁上,且blocking_session字段可能指向持锁者
这些字段组合起来,就构成一个“卡顿快照”。连续多个样本落在同一 sql_id + 同一 event 上,就是卡顿点的证据链。
- 必须加
sample_time > SYSDATE - INTERVAL '5' MINUTE:ASH 内存只保留约 1 小时,但高负载下可能更短;5 分钟窗口足够捕获瞬时尖刺,又不至于被历史噪声淹没 - 别只看
sql_id:同一sql_id可能对应不同sql_plan_hash_value,卡顿可能只发生在某一个子游标上 - 如果
sql_id为空,重点看program、module和event:可能是 PL/SQL 匿名块、递归调用或硬解析风暴
为什么不能依赖 AWR 报告里的“ASH 数据链接”
AWR 报告中嵌入的 ASH 摘要(如 “Top Sessions by DB Time” 下的链接)是按快照周期聚合过的,丢失了秒级精度。例如:
- AWR 快照间隔默认 60 分钟,而一次卡顿可能只持续 23 秒
- 报告里显示 “Top SQL by CPU” 是按累计 DB Time 排序,但真正拖垮系统的,往往是一条在 14:02:17–14:02:22 这 5 秒内密集执行、每次 800ms 的 SQL,它在 AWR 里可能排不进前 20
所以,真要定位卡顿点,必须绕过报告,直查 v$active_session_history,并用 TO_CHAR(sample_time, 'HH24:MI:SS') 对齐到秒。
RAC 环境下漏掉卡顿点的最常见错误
v$active_session_history 是单实例视图,RAC 中只返回当前节点的数据。如果卡顿发生在 node2,而你在 node1 上查 v$active_session_history,结果就是“没数据”。
- 必须用
gv$active_session_history,且所有节点时间截断逻辑一致:用TRUNC(sample_time, 'hh24'),别用TO_CHAR(sample_time, 'YYYY-MM-DD HH24')—— 后者受会话时区影响,node1 和 node2 返回的字符串可能错位 - 加
WHERE inst_id = &inst_id可辅助确认某节点是否真有异常样本,但不能替代全局扫描
卡顿点从来不在报告里“等着你发现”,它只存在于采样瞬间的 session_state、event、p1/p2 组合中。查得越近实时,字段关联越紧,卡顿点才越清晰。











