ASH是每秒采样的活动会话历史,能精准捕获短时抖动;它通过记录等待事件、阻塞会话等定位瞬时瓶颈,时间精度秒级但为概率采样,需结合时区、权限及时间对齐正确使用。
ASH 是什么,为什么它能抓住“一闪而过”的抖动
ASH(Active Session History)不是快照,是采样。每秒抓一次正在干活的会话状态,记录它在做什么、等什么、在哪条 SQL、属于哪个用户、耗在哪类等待事件上。AWR 报告里 DB Time 是平均值,15 分钟一拍,抖动再猛,也可能被平滑掉;而 ASH 能还原出第 127 秒时有 8 个会话全卡在 enq: TX - row lock contention 上——这就是阻塞源头。
- 抖动持续时间短于 30 秒?AWR 很可能漏掉,ASH 通常不会
- 不需要提前开启或配置,OceanBase 和 Oracle 都默认后台运行 ASH 采集任务
- 时间精度到秒级,但注意:采样是概率性的,不是 100% 连续,所以别指望还原每一毫秒,但足够定位“哪几十秒最堵”
怎么查:用 obclient 或 sqlplus 拉指定时间段的 ASH 报告
核心是调用内置视图或报告生成函数,不是靠图形界面点几下。OceanBase 用 oceanbase.__all_virtual_ash(需权限),Oracle 用 v$active_session_history 或封装好的 DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_TEXT。
- 先确认时间范围:比如抖动发生在
'2026-03-14 17:22:15' 到 '2026-03-14 17:22:45',务必用数据库所在时区
- OceanBase 示例(需 sys 租户权限):
SELECT * FROM oceanbase.__all_virtual_ash
WHERE sample_time BETWEEN '2026-03-14 17:22:15' AND '2026-03-14 17:22:45'
ORDER BY sample_time DESC LIMIT 200;
- Oracle 示例(更推荐用报告函数):
SELECT * FROM TABLE(DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_TEXT(
l_dbid => 123456789,
l_inst_num => 1,
l_btime => TO_DATE('2026-03-14 17:22:15', 'yyyy-mm-dd hh24:mi:ss'),
l_etime => TO_DATE('2026-03-14 17:22:45', 'yyyy-mm-dd hh24:mi:ss')));
- 别直接查
v$active_session_history 全表,它只保留最近 1 小时(Oracle)或 30 分钟(OB 默认),超时数据自动滚动丢弃
重点看什么:从等待事件反推真实瓶颈
ASH 最有价值的部分不是 SQL 文本,而是 event、p1text/p2text、blocking_session 这三列。它们告诉你“谁在等”“等什么”“被谁拦着”。
- 如果高频出现
enq: TX - row lock contention,立刻查 blocking_session 对应的 sql_id 和执行计划,大概率是未提交事务锁了热点行
- 出现大量
db file sequential read 且 current_obj# 相同,说明某张小表被反复单块读,可能是索引失效或绑定变量窥探失败
-
latch: cache buffers chains 高频?不是 I/O 问题,是热块争用,得看是不是没走索引导致全表扫描打爆 buffer chain
- 注意
session_state = 'WAITING' 才算真等待;'ON CPU' 表示真正在跑,不是卡住,别误判成瓶颈
容易踩的坑:时间对不上、权限不够、误读采样偏差
很多人拉完数据说“没看到异常”,其实是没绕开几个隐形门槛。
- 数据库服务器时间和应用日志时间不一致:务必用
SELECT SYSDATE FROM DUAL; 确认 DB 时间,再对齐业务报错时间戳
- 权限不足查不到
__all_virtual_ash 或 v$active_session_history:OceanBase 需 SELECT ON oceanbase.*,Oracle 需 SELECT_CATALOG_ROLE 或直接授 SELECT ANY DICTIONARY
- 把 ASH 当“全量 trace”:它只是每秒抽一个样本,如果抖动只持续 0.3 秒,且刚好错过采样点,就看不到。这时要配合
gv$session 实时查 + alert 日志中的 ORA- 错误交叉验证
- 忽略
sample_time 的粒度:OceanBase ASH 默认 1 秒采样,但高负载下可能合并或跳过,sample_time 字段本身可能有 200–500ms 偏差,别拿它做毫秒级归因
oceanbase.__all_virtual_ash(需权限),Oracle 用 v$active_session_history 或封装好的 DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_TEXT。
- 先确认时间范围:比如抖动发生在
'2026-03-14 17:22:15'到'2026-03-14 17:22:45',务必用数据库所在时区 - OceanBase 示例(需 sys 租户权限):
SELECT * FROM oceanbase.__all_virtual_ash WHERE sample_time BETWEEN '2026-03-14 17:22:15' AND '2026-03-14 17:22:45' ORDER BY sample_time DESC LIMIT 200;
- Oracle 示例(更推荐用报告函数):
SELECT * FROM TABLE(DBMS_WORKLOAD_REPOSITORY.ASH_REPORT_TEXT( l_dbid => 123456789, l_inst_num => 1, l_btime => TO_DATE('2026-03-14 17:22:15', 'yyyy-mm-dd hh24:mi:ss'), l_etime => TO_DATE('2026-03-14 17:22:45', 'yyyy-mm-dd hh24:mi:ss'))); - 别直接查
v$active_session_history全表,它只保留最近 1 小时(Oracle)或 30 分钟(OB 默认),超时数据自动滚动丢弃
重点看什么:从等待事件反推真实瓶颈
ASH 最有价值的部分不是 SQL 文本,而是 event、p1text/p2text、blocking_session 这三列。它们告诉你“谁在等”“等什么”“被谁拦着”。
- 如果高频出现
enq: TX - row lock contention,立刻查 blocking_session 对应的 sql_id 和执行计划,大概率是未提交事务锁了热点行
- 出现大量
db file sequential read 且 current_obj# 相同,说明某张小表被反复单块读,可能是索引失效或绑定变量窥探失败
-
latch: cache buffers chains 高频?不是 I/O 问题,是热块争用,得看是不是没走索引导致全表扫描打爆 buffer chain
- 注意
session_state = 'WAITING' 才算真等待;'ON CPU' 表示真正在跑,不是卡住,别误判成瓶颈
容易踩的坑:时间对不上、权限不够、误读采样偏差
很多人拉完数据说“没看到异常”,其实是没绕开几个隐形门槛。
- 数据库服务器时间和应用日志时间不一致:务必用
SELECT SYSDATE FROM DUAL; 确认 DB 时间,再对齐业务报错时间戳
- 权限不足查不到
__all_virtual_ash 或 v$active_session_history:OceanBase 需 SELECT ON oceanbase.*,Oracle 需 SELECT_CATALOG_ROLE 或直接授 SELECT ANY DICTIONARY
- 把 ASH 当“全量 trace”:它只是每秒抽一个样本,如果抖动只持续 0.3 秒,且刚好错过采样点,就看不到。这时要配合
gv$session 实时查 + alert 日志中的 ORA- 错误交叉验证
- 忽略
sample_time 的粒度:OceanBase ASH 默认 1 秒采样,但高负载下可能合并或跳过,sample_time 字段本身可能有 200–500ms 偏差,别拿它做毫秒级归因
enq: TX - row lock contention,立刻查 blocking_session 对应的 sql_id 和执行计划,大概率是未提交事务锁了热点行 db file sequential read 且 current_obj# 相同,说明某张小表被反复单块读,可能是索引失效或绑定变量窥探失败 latch: cache buffers chains 高频?不是 I/O 问题,是热块争用,得看是不是没走索引导致全表扫描打爆 buffer chain session_state = 'WAITING' 才算真等待;'ON CPU' 表示真正在跑,不是卡住,别误判成瓶颈- 数据库服务器时间和应用日志时间不一致:务必用
SELECT SYSDATE FROM DUAL;确认 DB 时间,再对齐业务报错时间戳 - 权限不足查不到
__all_virtual_ash或v$active_session_history:OceanBase 需SELECT ON oceanbase.*,Oracle 需SELECT_CATALOG_ROLE或直接授SELECT ANY DICTIONARY - 把 ASH 当“全量 trace”:它只是每秒抽一个样本,如果抖动只持续 0.3 秒,且刚好错过采样点,就看不到。这时要配合
gv$session实时查 + alert 日志中的ORA-错误交叉验证 - 忽略
sample_time的粒度:OceanBase ASH 默认 1 秒采样,但高负载下可能合并或跳过,sample_time字段本身可能有 200–500ms 偏差,别拿它做毫秒级归因
复杂点在于:抖动未必是单一原因。可能先是大量短事务抢同一行锁,引发 tx 等待;接着触发大量回滚段写入,又拖慢 lgwr;最后连带 log file sync 升温。ash 能分层切出这些链式反应,但得你自己按时间戳串起来看——没人替你画因果图。











