直接查sample_time会漏掉并发峰值,因ash采样非整秒对齐且存在毫秒级偏移,导致between区间遗漏高峰;应改用sample_id分组统计每秒活跃会话数,并结合client_identifier关联web请求链路。
为什么直接查 sample_time 会漏掉并发峰值
ash 每秒采样一次,但样本不是严格对齐在整秒边界——实际时间戳如 2026-05-11 03:18:22.473,而你用 sample_time between ... 包死区间时,若并发高峰恰好发生在 03:18:22.999,且下一条采样落在 03:18:23.005(跳过了 .000),就可能被 between '03:18:22' and '03:18:23' 漏掉。更糟的是,多个会话在毫秒级内密集触发,却分散在相邻两个 sample_time 值里,导致单个时间点看起来“不忙”,实际是峰值平摊了。
实操建议:
- 别用
BETWEEN,改用SAMPLE_TIME > SYSDATE - INTERVAL '3' MINUTE动态兜底,确保覆盖最近窗口 - 真正定位并发密度,得靠
SAMPLE_ID:它是 Oracle 内部单调递增的采样序号,同一秒内多个会话的样本共享一个SAMPLE_ID,但不同秒一定不同 -
SAMPLE_ID在 RAC 环境下跨实例全局唯一,比SAMPLE_TIME更可靠——尤其当节点间时钟有微小漂移时
用 SAMPLE_ID 聚合每秒活跃会话数
并发高峰的本质是「单位时间内的活动会话数量突增」,SAMPLE_ID 是最稳的分组依据。以下查询能还原真实每秒压力曲线:
SELECT SAMPLE_ID,
COUNT(*) AS active_sessions,
MIN(SAMPLE_TIME) AS sample_ts,
COUNT(DISTINCT SESSION_ID) AS unique_sessions,
COUNT(CASE WHEN SESSION_STATE = 'ON CPU' THEN 1 END) AS cpu_samples,
COUNT(CASE WHEN EVENT LIKE 'enq:%' THEN 1 END) AS enqueue_waits
FROM V$ACTIVE_SESSION_HISTORY
WHERE SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE
GROUP BY SAMPLE_ID
ORDER BY SAMPLE_ID DESC
FETCH FIRST 20 ROWS ONLY;
注意点:
- 结果中
active_sessions高不代表真卡顿——要结合cpu_samples和等待事件看是 CPU 密集型还是锁争用型 - 如果某
SAMPLE_ID下unique_sessions远小于active_sessions,说明大量会话卡在同一个阻塞点(比如同一条 SQL 的硬解析、或同一行的 TX 锁) -
SAMPLE_ID降序排列可快速看到最新高峰;若想看趋势,加TO_CHAR(MIN(SAMPLE_TIME), 'HH24:MI:SS')辅助对齐时间
如何把 Web 请求链路和 SAMPLE_ID 对上
ASH 本身不存 HTTP 请求 ID 或 trace_id,但 Web 应用可通过 DBMS_SESSION.SET_IDENTIFIER 把请求上下文带进来。只要应用在获取连接后立刻执行:
BEGIN DBMS_SESSION.SET_IDENTIFIER('req_abc123_xyz'); END;
后续该连接产生的所有 ASH 样本,SESSION_ID 对应的 CLIENT_IDENTIFIER 字段就会是 req_abc123_xyz。此时就能反向查:
SELECT a.SAMPLE_ID, a.SAMPLE_TIME, a.EVENT, a.SQL_ID,
s.CLIENT_IDENTIFIER
FROM V$ACTIVE_SESSION_HISTORY a
JOIN V$SESSION s ON a.SESSION_ID = s.SID AND a.SESSION_SERIAL# = s.SERIAL#
WHERE s.CLIENT_IDENTIFIER = 'req_abc123_xyz'
AND a.SAMPLE_TIME > SYSDATE - INTERVAL '2' MINUTE;
关键约束:
- 必须用
V$SESSION关联,不能只查V$ACTIVE_SESSION_HISTORY——后者没有CLIENT_IDENTIFIER字段 - 如果应用用连接池(如 HikariCP),需确认是否每次借出连接后都重设
CLIENT_IDENTIFIER,否则会复用旧值 - Oracle 12c+ 才支持在
V$SESSION_CONNECT_INFO中查到更细的客户端信息(如NETWORK_SERVICE_BANNER),但依赖监听器配置,不如主动埋点稳定
SAMPLE_ID 分析容易忽略的三个边界
SAMPLE_ID 看似简单,但 Web 场景下有三处极易踩坑:
- 内存保留限制:
V$ACTIVE_SESSION_HISTORY只缓存约 1 小时数据(受_ash_size控制),SAMPLE_ID不是永久序列。查历史问题必须转向DBA_HIST_ACTIVE_SESS_HISTORY,但它按 AWR 快照粒度归档(默认每小时 1 次),丢失秒级细节 - 采样盲区:当会话处于
WAITING状态但EVENT为空(如硬解析卡在 library cache lock),ASH 可能不记录该样本,SAMPLE_ID就断了——此时要补查V$SESSION的STATE和EVENT字段 - Web 层超时干扰:前端设置 30s 超时,但数据库侧会话可能还在等
log file sync。这时SAMPLE_ID序列会持续增长,但对应请求早已失败,单纯数SAMPLE_ID密度会高估真实负载











