ASH采样机制本质是概率性快照,每秒仅捕获活跃会话状态,不记录执行耗时小于1秒或未覆盖整秒窗口的SQL;其设计目标是定位拥塞时段与等待事件,而非捕捉毫秒级操作。
ASH 采样机制本质是概率性快照,不是全量记录
ash 每秒对活跃会话做一次状态捕获,gv$ob_active_session_history 或 v$active_session_history 中每一行,只代表“该会话在那一秒被采样到且处于活跃状态”。它不追踪 sql 的起止时间,也不记录执行耗时小于采样间隔的完整生命周期。
- 如果一条 SQL 实际执行耗时仅 200ms,而采样恰好发生在它开始前或结束后,就不会留下任何记录
- 即使执行跨了两个采样点(比如 09:10:05.300 开始,09:10:05.480 结束),只要它没在
09:10:05或09:10:06这两个整秒时刻处于“活跃”状态(如正在解析、等待、执行中),就无法被捕获 - OceanBase 和 Oracle 都使用相同逻辑:采样线程在固定时间点轮询,不插值、不补帧、不回溯
SQL_ID 出现但执行时间显示异常长?大概率是阻塞或解析卡住
你看到某条 SQL_ID 在 ASH 里有多个样本、且 sample_time - sql_exec_start 差值达几十秒,不代表 SQL 本身跑了那么久。更可能是:
-
SESSION_STATE = 'WAITING'且EVENT = 'enq: TX - row lock contention':SQL 已发出去,但卡在锁等待上,ASH 把整个等待期都算进“执行中” -
SESSION_STATE = 'PARSING':硬解析阶段被 library cache latch 卡住,ASH 记录的是“解析 + 执行”总挂起时间 - PL/SQL 块内循环调用同一条 SQL:每次采样落在不同迭代,看起来像单次执行超长,实际是多次短执行
想确认是否真漏掉了短 SQL?别只盯 ASH,交叉验证三处关键数据
单独看 ASH 容易误判。必须结合以下视图比对时间、次数和执行特征:
- 查
v$sql中该SQL_ID的elapsed_time / executions平均值:若平均仅几毫秒,但 ASH 显示大量 >1s 样本,说明问题不在执行本身 - 查
v$sql_plan_statistics_all的last_elapsed_time和last_starts:确认最近一次真实执行耗时与频次 - 查
dba_hist_sqltext(而非v$sqlarea)获取 SQL 文本:避免因共享池老化导致文本丢失,影响判断上下文
真正能抓到 sub-second 级 SQL 的方式,ASH 不提供
ASH 的设计目标从来不是捕捉毫秒级操作,而是定位“哪几十秒最堵、谁在等什么”。如果你需要确认某条 SQL 是否真的在某个瞬间被执行过,且耗时极短:
- 启用 SQL Trace(
ALTER SESSION SET EVENTS '10046 trace name context forever, level 8'):它记录每条 SQL 的精确起止时间,但开销大,不可长期开启 - 用
DBA_HIST_SQLSTAT查 AWR 中聚合后的执行统计:能看到executions_delta和elapsed_time_delta,但粒度是 1 小时快照,无法定位具体秒级事件 - 依赖应用层日志或数据库审计(
unified_audit_trail):记录 SQL 提交时间戳,但不包含执行耗时
所以当别人说“ASH 没抓到那条 SQL”,先别急着怀疑配置或权限——大概率它确实一闪而过,连 1 秒的采样窗口都没撞上。这时候,与其反复刷 ASH,不如去查那段时间的锁链、解析争用或网络中断痕迹。


















