查ASH需加BLOCKING_SESSION IS NOT NULL和WAIT_TIME = 0以定位实时阻塞链,时间范围建议5分钟内,p3字段解出namespace和mode定位对象类型,RAC环境需关注BLOCKING_INSTANCE,关联SQL_ID时必须同时取SQL_PLAN_HASH_VALUE。
查ASH必须加BLOCKING_SESSION IS NOT NULL和WAIT_TIME = 0
只写event = 'library cache lock'会捞出大量历史残留或已释放的等待,根本找不到真正在卡住的会话。关键是要定位“此刻正被堵着”的活跃链。必须在查询dba_hist_active_sess_history时强制带上两个条件:blocking_session is not null(说明有明确阻塞源头),以及wait_time = 0(表示该会话当前处于等待中,不是刚结束或采样间隙)。时间范围建议控制在5分钟内,比如sample_time between to_date('2026-05-15 08:10', 'yyyy-mm-dd hh24:mi') and to_date('2026-05-15 08:15', 'yyyy-mm-dd hh24:mi')。
从p3字段解出namespace和mode定位对象类型
p3是十六进制值,格式为100 * mode + namespace。例如0x4f0003拆解后:低两位03 → mode=3(独占锁),高位4f → namespace=79。这个79不是随便编的,它对应ACCOUNT_STATUS——立刻转向查dba_audit_session,而不是继续翻SQL。常见namespace值可查x$kglst:SELECT indx, kglstdsc FROM x$kglst WHERE kglsttyp='NAMESPACE' AND indx IN (79, 1, 2)。注意:RAC环境下要同时看BLOCKING_INSTANCE,跨节点锁不会出现在本地v$session里。
关联SQL_ID必须连带SQL_PLAN_HASH_VALUE一起捞
单靠SQL_ID可能不准,因为不同子游标可能共享同一SQL_ID但执行计划完全不同。一定要把SQL_PLAN_HASH_VALUE一并取出,再用这两个字段去关联dba_hist_sqltext。很多硬解析风暴就藏在WHERE item_id IN ('123','456')这种拼字符串的SQL里——每次参数组合都生成新游标,version_count飙到几百上千,executions却很低。如果发现v$sqlarea.version_count > 50且executions ,基本就是绑定变量没用或SQL文本不一致。
ASH只是采样,v$session才是实时快照
ASH每秒采样一次,漏掉瞬时阻塞很常见。一旦在ASH里看到可疑的blocking_session,立刻切到实时视图:SELECT sid, serial#, sql_id, event, blocking_session, seconds_in_wait FROM v$session WHERE event = 'library cache lock'。对查出的blocking_session号,再查v$sqlarea看它的version_count和executions比值;同时检查v$sql_bind_capture里有没有VARCHAR2绑定变量传了NULL(Bug 8198150典型表现)。别忘了sql_text里是否含TO_DATE('2026-05-15')这类字面量,或者JDBC自动注入的/* ApplicationName=xxx */注释——这些都会让Oracle判定为新SQL。











