ASH每秒采样一次,无法捕获亚秒级抖动,本质是快照式轮询,短于1秒的等待事件(如300ms网络超时)大概率被遗漏,导致高并发短事务场景下阻塞链误判为偶发;其统计天然偏向长耗时事件,且SGA环形缓冲区易被覆盖,需结合DBMS_MONITOR、v$session、dba_hist_active_sess_history等多源验证。
ASH每秒采样一次,但sub-second抖动根本捕获不到
ash的采样机制本质是“快照式轮询”,由mmnl进程每秒触发一次,只记录那一瞬间会话状态。如果真实问题持续时间远小于1秒(比如某次网络超时仅300ms、硬解析卡顿450ms),它大概率被跳过——不是没发生,是根本没拍到。
这种遗漏在高并发短事务场景下尤其明显:大量enq: TX - row lock contention实际只持续200~600ms,ASH里可能只看到零星几条记录,误判为偶发;而真实阻塞链其实高频存在。
- 验证方法:查
v$system_event中time_waited_micro与wait_count比值,若平均等待时长明显低于1000ms,ASH采样就不可靠 - 替代手段:配合
DBMS_MONITOR.SESSION_TRACE_ENABLE对可疑会话做细粒度跟踪 - 注意:
V$SESSION的event和state字段是实时的,但没历史回溯能力,不能代替ASH
采样偏差让短等待事件“隐身”,长等待被过度放大
ASH不是均匀采样。一个持续100ms的等待事件,被采中的概率约10%;而持续1s的等待,几乎必中。这就导致统计结果天然偏向长耗时事件——比如db file sequential read在ASH里占比很高,但实际可能是几百次微秒级单块读叠加所致,掩盖了真正瓶颈。
典型误导现象:v$active_session_history显示某SQL 90%时间在direct path read,但dba_hist_sqlstat里该SQL的elapsed_time却很低。这是因为ASH把多次短读合并计为“同一类等待”,而实际业务感知不到卡顿。
- 关键参数:
_ash_disk_filter_ratio控制写入磁盘的比例,默认1/10,进一步稀释短事件留存 - 查证技巧:用
COUNT(*) OVER (PARTITION BY sql_id, event ORDER BY sample_time RANGE BETWEEN INTERVAL '1' SECOND PRECEDING AND CURRENT ROW)窗口函数估算事件密度,比单纯看COUNT更准 - 别只盯
event列,必须结合session_state(ON CPU / WAITING)和time_model字段交叉判断
内存环形缓冲区满后,新采样覆盖旧数据,时间窗口不可控
v$active_session_history的数据存在SGA的环形缓冲区里,大小由隐含参数_ash_size决定。12c默认仍是约4MB,撑不住高负载——比如每秒活跃会话超200个,缓冲区实际保留时间可能不足10分钟,而非文档说的“约1小时”。
结果就是:刚发现卡顿,立刻查WHERE sample_time > SYSDATE - 1/1440(过去1分钟),却返回空。不是没数据,是那1分钟前的采样已被覆盖,而你查的时间段恰好落在“覆盖缺口”里。
- 确认是否真丢失:执行
SELECT MIN(sample_time), MAX(sample_time) FROM v$active_session_history,看时间跨度是否远小于60分钟 - 调大缓冲区需重启实例:
ALTER SYSTEM SET "_ash_size"=524288000 SCOPE=SPFILE(500MB),但要同步检查sga_max_size是否足够 - 紧急排查时,优先查
dba_hist_active_sess_history(磁盘归档版),虽然延迟1小时,但至少有数据
ASH不记录空闲会话和后台进程活动,两类问题直接漏检
ASH只采非空闲状态(session_state != 'INACTIVE')且正在消耗资源的会话。这意味着:前台应用已提交、但后台进程(如CKPT、DBWR)因I/O卡住导致整体响应变慢时,ASH里可能一片“安静”——因为前台会话全在空闲等待,根本不会被采。
另一个盲区是递归调用:比如大量硬解析触发的library cache lock,会话状态常为WAITING但event为NULL,ASH里只记一行空事件,无法定位根因。
- 补救方案:必须联合查
v$session(看status、sql_id、blocking_session)、v$process(查background标志)、v$sql(找parse_calls突增的SQL) - 特别注意
final_blocking_session字段,12c+才稳定输出,它是穿透级联阻塞链的关键 - 遇到
ON CPU但sql_id为空的情况,重点查program和machine,常是应用端连接池或JDBC驱动行为异常
诊断精度的瓶颈不在SQL写得有多漂亮,而在你是否清楚ASH哪一秒拍到了、哪一秒彻底错过、哪一段数据早已被覆盖。它是个高保真但有明确物理边界的录像机,不是全知视角。


















