ash查不到最近活跃会话,因采样每秒一次且内存仅保留约1小时数据;需检查采样是否启用、时间窗口是否足够,并优先用where sample_time > sysdate - 1/1440过滤。
ash视图查不到最近的活跃会话?检查采样是否启用且时间窗口够用
oracle的v$active_session_history(ash)默认每秒采样一次,但只保留内存中约1小时的数据(具体取决于_ash_size和负载),磁盘上归档的dba_hist_active_sess_history则依赖awr快照频率(默认每小时1次)。如果刚遇到卡顿就查v$ash却返回空,大概率是采样还没来得及捕获,或会话已退出、采样被覆盖。
实操建议:
- 立即排查时优先查
V$ACTIVE_SESSION_HISTORY,加WHERE sample_time > SYSDATE - 1/1440(过去1分钟)缩小范围 - 确认AWR是否启用:
SELECT dbid, name, startup_time FROM v$database;+ 检查dba_hist_snapshot是否有近期记录 - 若需更细粒度,可临时提高ASH内存保留量(需重启实例):
ALTER SYSTEM SET "_ash_size"=524288000 SCOPE=SPFILE;(500MB) - 注意:
V$ASH不包含ON CPU状态为WAITING但等待事件为NULL的会话——这类通常是硬解析或递归调用阻塞,得结合V$SESSION和V$SQL交叉验证
查出大量enq: TX - row lock contention但找不到阻塞源?重点看blocking_session和final_blocking_session
ASH里看到高频enq: TX - row lock contention,不代表能直接定位谁锁了谁。因为ASH采样的是“正在等”的瞬间,而持锁会话可能早已提交/回滚,或根本没被采样到(比如锁持有时间短于1秒)。
实操建议:
- 不要只查
event字段,必须连查session_id,blocking_session,final_blocking_session三列,后者在12c+才稳定可用 - 执行:
SELECT session_id, blocking_session, final_blocking_session, sql_id, event, p1text, p1 FROM v$active_session_history WHERE event = 'enq: TX - row lock contention' AND sample_time > SYSDATE - 1/720 ORDER BY sample_time DESC; - 若
blocking_session为空但final_blocking_session有值,说明中间存在级联阻塞(A→B→C),需顺藤摸瓜查C的V$SESSION状态 - 注意:某些TX锁由DDL隐式触发(如
ALTER TABLE ... MOVE),此时sql_id可能为NULL,得结合machine和program字段人工排查应用行为
ASH显示大量cursor: pin S wait on X?不是SQL写法问题,而是Library Cache争用
这个等待事件常被误认为“SQL没绑定变量”,其实本质是多个会话同时尝试获取同一游标句柄的共享锁(S),但该游标正被另一个会话以排他模式(X)修改(比如硬解析、刷新执行计划、刷新结果集缓存)。它反映的是Library Cache Latch或Mutex争用,而非SQL本身低效。
实操建议:
- 先确认是否真有硬解析:查
V$SQL中parse_calls远大于executions,或V$SYSSTAT里parse count (hard)突增 - 检查是否存在频繁
DBMS_SHARED_POOL.PURGE或ALTER SYSTEM FLUSH SHARED_POOL操作——这些会强制失效大量游标,引发后续集中重解析 - 若应用使用动态SQL且
cursor_sharing=FORCE,反而可能加剧Mutex争用;12c+建议改用cursor_sharing=EXACT+ 应用层绑定变量 - 紧急缓解可临时增大
_kks_use_mutex_pin(11gR2+默认TRUE),但治标不治本;根因还是减少游标失效和避免无谓的硬解析
用ASH聚合分析Top SQL时,为什么sql_id统计不准?别忽略in_connection_mgmt和in_parse状态
ASH按sql_id聚合等待时间,容易漏掉两类关键开销:一是连接建立/断开阶段(如DRCP连接池切换),二是SQL文本解析阶段(非执行)。这两部分在ASH中sql_id为NULL,但session_state可能是IN CONNECTION MANAGEMENT或IN PARSE,实际耗时可能占整体响应时间30%以上。
实操建议:
- 做Top SQL分析时,必须补查:
SELECT session_state, event, COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/24 GROUP BY session_state, event ORDER BY 3 DESC; - 若发现大量
IN PARSE且event为空,说明SQL文本解析慢——检查是否启用了cursor_space_for_time=TRUE(已废弃)或存在超长SQL(>10MB) - 若
IN CONNECTION MANAGEMENT占比高,且program多为oracle@... (J000),大概率是调度作业(DBMS_SCHEDULER)密集建连,应改用连接池或调整作业并发度 - 注意:
sql_id相同不意味执行计划相同——不同绑定变量值可能触发不同计划,需结合plan_hash_value二次分组
ASH是实时性能诊断的利器,但它只是快照,不是录像。真正难的不是查出哪个SQL在等,而是判断“它为什么在这个时刻等”——这需要把ASH数据和V$SESSION、V$LOCK、V$SQL_PLAN甚至OS层面的top输出串起来看。尤其当等待集中在latch: shared pool或library cache: mutex X这类底层资源时,单靠ASH字段几乎无法定位,必须切到V$LATCH_CHILDREN或V$MUTEX_SLEEP深挖。











