oracle中不存在“library cache load lock”等待事件,正确名称为library cache lock或library cache pin;排查时需结合blocking_session、wait_time=0及最近5分钟采样,并解析p3定位锁类型,rac环境必须使用gv$active_session_history。
library cache load lock 不是标准等待事件名,oracle 官方等待事件中只有 library cache lock 和 library cache pin,没有 library cache load lock。你看到的这个名称,大概率是误记、日志拼写错误,或监控工具对 library cache lock 的非标翻译(比如把“load”当成动词理解了)。真实排查必须回归到 oracle 原生视图和事件定义。
查 v$active_session_history 时为什么不能只写 event = 'library cache lock'
单纯过滤 event = 'library cache lock' 会捞出大量已结束、已释放、甚至采样噪声的记录,根本无法定位正在卡住的源头。ASH 是每秒一次的快照,不是实时流,漏掉瞬时阻塞很常见。真正有效的条件组合是:
-
BLOCKING_SESSION IS NOT NULL:说明有明确的阻塞者,不是孤立等待 -
WAIT_TIME = 0:表示该会话当前正卡在等待中,不是刚完成或采样间隙 -
SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE:用动态时间区间,避免时区或 NLS 设置导致查空
示例查询:
SELECT sql_id, sql_opname, event, p3, blocking_session, sample_time FROM v$active_session_history WHERE event = 'library cache lock' AND blocking_session IS NOT NULL AND wait_time = 0 AND sample_time > SYSDATE - INTERVAL '5' MINUTE ORDER BY sample_time DESC;
从 p3 字段反推锁对象类型,比看 sql_text 更可靠
p3 是十六进制值,格式为 100 * mode + namespace。例如 0x4f0003 拆解后:
低两位 03 → mode = 3(独占锁)
高位 4f(十进制 79)→ namespace = 79,对应 ACCOUNT_STATUS,不是 SQL 对象,而是认证层状态。
- 查
namespace含义:运行SELECT indx, kglstdsc FROM x$kglst WHERE kglsttyp='NAMESPACE' AND indx IN (1,2,79) -
namespace = 79时,立刻转向DBA_AUDIT_SESSION查失败登录:SELECT username, os_username, userhost, extended_timestamp, returncode FROM dba_audit_session WHERE returncode != 0 AND extended_timestamp > SYSDATE - 1/24 -
namespace = 1(TABLE/PROCEDURE)或2(BODY)才需要查v$db_object_cache或dba_objects
阻塞链顶端会话的 sql_id 为空?别慌,用 sql_opname 和 v$session 补位
DDL 编译阶段(如 CREATE OR REPLACE PACKAGE BODY)可能尚未生成完整 sql_id,ASH 中显示为空或全零。此时关键线索是:
-
sql_opname IN ('CREATE','ALTER','DROP','GRANT','REVOKE'):直接锁定 DDL 类型 - 查
v$session实时快照:SELECT sid, serial#, sql_opname, sql_text, event, blocking_session FROM v$session WHERE event = 'library cache lock' - 对查出的
blocking_session,再查v$sqlarea:SELECT version_count, executions, sql_text FROM v$sqlarea WHERE sql_id = '&blocked_sql_id';若version_count > 50且executions极低,说明是硬解析风暴,不是 DDL 本身的问题
RAC 环境下必须用 gv$active_session_history,且关注 BLOCKING_INSTANCE
跨节点的锁不会出现在本地 v$active_session_history 里。只查当前实例,等于只看半张地图。
- 必须用
gv$active_session_history,而非v$前缀视图 -
BLOCKING_INSTANCE字段告诉你阻塞者在哪台节点上,否则你可能在节点1上疯狂查,而真凶在节点3上安静地持锁 - 如果
BLOCKING_INSTANCE和当前INSTANCE_NUMBER不同,立刻切到对应节点执行v$session查询
最易被忽略的一点:ASH 里的 sql_id 和 SQL_PLAN_HASH_VALUE 必须一起取,单靠 sql_id 关联 dba_hist_sqltext 可能错配子游标——同一个 sql_id 下可能有几十个不同执行计划,而真正拖住 library cache 的,往往只是其中某一个特定子游标。











