ASH能快速定位library cache pin阻塞源头,但需联查x$kglob和x$kglpn确认被锁对象及持有者;因ASH采样含时间维度,对瞬时等待更敏感,而v$session_wait易漏短于3秒的等待。
直接结论:ash(v$active_session_history)能快速定位 library cache pin 的阻塞源头,但必须配合 x$kglob 和 x$kglpn 才能确认被锁定的对象和持有会话;单纯查 ash 只能看到等待,看不到谁在 hold。
为什么 v$active_session_history 比 v$session_wait 更适合初筛?
因为 ASH 是采样视图,自带时间维度和堆栈上下文,对瞬时、间歇性或已结束的 pin 等待更敏感。v$session_wait 只反映当前“正在等”的会话,而很多 library cache pin 等待持续不到 3 秒就超时退出,v$session_wait 很容易漏掉。
关键点:
- ASH 中
event='library cache pin'的记录,其p1raw字段就是被争用对象的 KGL Handle 地址(即x$kglob.kglhdadr) - ASH 同时记录了
blocking_session和blocking_session_serial#,但注意:这个字段对 library cache pin **通常为空或不准**——因为 pin 阻塞不是传统会话级阻塞,而是共享池内部结构竞争 - 所以不能依赖
blocking_session,必须用p1raw去关联底层基表
怎么用 ASH + x$kglob 定位具体被锁的对象?
先从 ASH 抓最近 1 小时内最频繁的等待样本:
SELECT p1raw, COUNT(*) cnt FROM v$active_session_history WHERE event = 'library cache pin' AND sample_time > SYSDATE - 1/24 GROUP BY p1raw ORDER BY cnt DESC FETCH FIRST 5 ROWS ONLY;
拿到 top p1raw 值(如 '00000008A1234567')后,立刻查对象信息:
SELECT kglnaown, kglnaobj, kglnahsh, kglhdflg FROM x$kglob WHERE kglhdadr = '00000008A1234567';
这里要注意:
-
kglnaown和kglnaobj是对象所有者和名称,但可能为 NULL(比如匿名 PL/SQL 块) -
kglhdflg若含0x200000(即十进制 2097152),说明该对象当前处于 INVALID 状态,大概率正被重编译 - 如果
kglnaobj是空或像__anonymous_block这类,说明是动态 SQL 或未命名 PL/SQL,需结合sql_id追踪
怎么确认哪个会话在 hold 这个 pin?
不能只看 v$session,必须查内核级 pin 表 x$kglpn,它记录每个 pin 的持有者和请求者:
SELECT s.sid, s.serial#, s.username, s.program,
p.kglpnmod, p.kglpnreq, p.kglpnhdl
FROM v$session s, x$kglpn p
WHERE s.saddr = p.kglpnuse
AND p.kglpnhdl = '00000008A1234567'
AND p.kglpnmod != 0;重点看 kglpnmod 值:
-
1= Null 模式(基本可忽略) -
2= Share 模式(常见于执行中过程、SQL 解析) -
3= Exclusive 模式(**这才是罪魁祸首**,通常是 DDL、CREATE OR REPLACE、GRANT 等操作)
如果发现多个会话的 kglpnmod = 3,说明有并发编译冲突;若只有 1 个且 seconds_in_wait 很大,极可能是该会话卡在重编译(比如依赖链太深、统计信息缺失导致硬解析慢)。
容易被忽略的细节:P3 编码里藏着 namespace 和 mode
v$active_session_history.p3 是一个编码值:10 * mode + namespace。例如 P3=20 表示 mode=2(Share)、namespace=0(SQL AREA);P3=30 表示 mode=3(Exclusive)、namespace=0。
namespace 常见值:
-
0= SQL AREA(最常见) -
1= TABLE/PROCEDURE(PL/SQL 对象) -
2= PACKAGE BODY -
3= TRIGGER
这意味着:如果 P3=31,说明是 namespace=1(PROCEDURE)上的 Exclusive pin —— 直接指向某个存储过程正被重建,不用再猜。
真正棘手的从来不是“怎么查”,而是查到 kglpnmod = 3 的会话后,发现它卡在一条看似简单的 CREATE OR REPLACE PROCEDURE 上——这时往往要检查依赖对象是否 INVALID、是否有隐式递归编译、甚至 shared pool 是否碎片化。这些没法靠一条 SQL 解决,得看上下文。


















