查v$active_session_history必须用动态时间窗口,因ASH内存仅保留约1小时且高负载下更短;应使用SAMPLE_TIME > SYSDATE - 30/1440,避免写死时间字符串或BETWEEN导致漏样;RAC环境须用gv$active_session_history。

查 v$active_session_history 必须用动态时间窗口
ASH 内存缓冲区默认只保留约 1 小时,且高负载下可能被快速覆盖。写死时间字符串(如 '2026-10-27 15:30:00')极易因采样非连续性或会话时区差异漏掉关键样本。
正确做法是用 SAMPLE_TIME > SYSDATE - 30/1440(30 分钟前),这个表达式在 11gR2 及以上都兼容,不依赖 INTERVAL 语法,也避免 NLS 设置干扰。
- 别用
BETWEEN:比如SAMPLE_TIME BETWEEN ... AND ...容易因采样点落在边界外而丢样本(例如问题发生在15:29:59.8,但采样只在.0/.1/.2秒发生) - RAC 环境必须查
gv$active_session_history,否则只看到当前节点的会话,挂起若发生在其他实例就完全不可见 - 如果数据库已完全 hang 死、SQL 无法执行,优先连到 idle instance 用
oradebug触发 systemstate dump,再回头补 ASH 分析
过滤等待事件要盯紧 enq: TX% 和 session_state = 'WAITING'
挂起往往表现为大量会话卡在锁等待上,但不是所有 enq: TX% 都代表真行锁——enq: TX - allocate ITL entry 是 ITL 不足,enq: TX - index contention 是索引块争用,它们和挂起关系较弱。
真正指向挂起根因的组合是:
-
event LIKE 'enq: TX%'且session_state = 'WAITING' -
CURRENT_OBJ#高度集中(比如连续多行都是同一对象 ID,说明热点表明确) -
blocking_session非空,且链路可追溯(注意 RAC 下得看final_blocking_session和final_blocking_instance) - 若
p1raw值为'54580006',确认是 mode=6 的真实行锁;若为'54580004',大概率是唯一键冲突或 ITL 不足,杀会话无用
关联用户名和 SQL 文本不能靠猜字段
v$active_session_history 没有 username 字段,直接 SELECT username 必报 ORA-00904;它也没有 sql_text,只存 sql_id。
要还原上下文,必须显式关联:
- 用户名:
JOIN dba_users u ON ash.user_id = u.user_id,别用v$session关联,因为会话可能已断开 - SQL 文本:先查
v$sql,若为空再查DBA_HIST_SQLTEXT(AWR 里存的历史文本),只要该 SQL 曾进过 AWR 快照就有机会恢复 - 模块信息:
MODULE比PROGRAM更稳定,应用规范接入时通常填入服务名(如'INVENTORY_SERVICE')
别等 AWR 报告,ASH 是唯一能抓到“正在挂”的证据
AWR 报告滞后,最小快照间隔通常 15–30 分钟,生成还要时间。等它出来时,事务可能已回滚、会话已断开、ASH 缓冲区已被覆盖——你面对的是一片空白。
挂起诊断的关键窗口只有几分钟:从用户反馈“卡了”,到你连上数据库执行第一条 SQL,中间每延迟 1 分钟,证据丢失风险就指数级上升。
最危险的误操作是:看到 enq: TX% 就急着 ALTER SYSTEM KILL SESSION。没确认 final_blocking_session 所在实例、没验证 p1raw 模式、没查 gv$transaction 看事务是否仍在活跃,盲目 kill 可能引发连锁回滚甚至实例崩溃。











