Library Cache Lock 是 Oracle 解析 SQL 或执行 DDL 时对共享池中对象定义加的内存结构锁;RAC 下因 GRD 协调开销、共享池碎片及 DDL 隐式持锁过长,易引发跨节点阻塞和长时间等待。
Library Cache Lock 是什么,为什么 RAC 下特别疼
它不是锁表,是 oracle 在解析 sql 或执行 ddl 时,对共享池中对象定义(比如包、视图、同义词)加的内存结构锁。单实例里等几毫秒就过了;rac 下,这个锁要跨节点协调,一旦有未提交的 ddl 或长时间 parse,library cache lock 就卡住其他节点的相同对象访问,表现为会话长时间 waiting on 'library cache lock',且 p1text 显示 handle address,p2text 是 lock address。
根本原因不是锁本身重,而是 RAC 的全局资源目录(GRD)同步开销 + 共享池碎片化 + 某些 DDL 隐式持有锁时间过长(比如 CREATE OR REPLACE PACKAGE 会先 drop 再 create,中间窗口被抢占)。
DDL 操作必须加 ALTER SYSTEM FLUSH SHARED_POOL 吗
不加不一定错,但加了大概率出事——这是最常踩的坑。RAC 中 FLUSH SHARED_POOL 是全局广播操作,所有节点清空本地 shared pool,触发大量硬解析和重新加载,瞬间放大 Library Cache Lock 和 Cursor: pin S wait on X 等等待。
真正该做的是精准清理:
- 用
DBMS_SHARED_POOL.PURGE清特定对象:EXEC DBMS_SHARED_POOL.PURGE('PKG_NAME', 'P')('P'表示 package) - 确认对象是否在 shared pool:查
V$DB_OBJECT_CACHE,过滤type IN ('PACKAGE', 'PROCEDURE', 'FUNCTION')且kept = 'NO' - 避免在业务高峰执行 DDL;如果必须,先在目标节点用
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12'捕获 parse 路径,确认是否真因缓存失效引发连锁等待
RAC 节点间 DDL 不一致导致隐式锁升级
典型场景:节点 1 执行 CREATE OR REPLACE VIEW v_test AS SELECT * FROM t1,还没提交;节点 2 同时查询 v_test。这时节点 2 不仅等 Library Cache Lock,还可能触发 DFS lock handle 等待——因为 view 定义变更需 GRD 协调,而未提交事务阻塞了全局元数据同步。
解决关键在事务边界和对象依赖管理:
- 所有跨节点 DDL 必须显式
COMMIT,禁止隐式 autocommit(如某些 JDBC 驱动默认开启) - 避免在 DDL 前后立即查依赖对象;例如改包体前,先用
SELECT * FROM DBA_DEPENDENCIES WHERE REFERENCED_NAME = 'PKG_NAME'梳理调用链,暂停上游应用 - 检查
V$LOCK中TYPE = 'AE'(application enqueue)和TYPE = 'RT'(redo thread)锁,它们常与未完成 DDL 关联
共享池设置不当放大竞争:_kghdsidx_count 和 SHARED_POOL_SIZE 怎么调
RAC 默认 _kghdsidx_count = 7(shared pool hash bucket 数),节点多但 bucket 少,所有对象哈希到有限 slot,冲突概率飙升。这不是文档参数,但实测调整后 Library Cache Lock 平均等待下降 40%+。
调参要点:
- 设为质数,略大于节点数 × 2:4 节点 RAC 可试
_kghdsidx_count = 11,需所有节点统一设置并重启实例 -
SHARED_POOL_SIZE不能只看总量,要看各节点分配是否均衡;查V$SGASTAT中free memory是否持续 - 禁用
RESULT_CACHE_MAX_SIZE(除非真用 result cache):它和 library cache 共享同一片 latch,开启后library cache lock等待明显增加
这些参数没标准值,上线前必须在测试 RAC 环境跑真实负载压测;生产直接改 _kghdsidx_count 而不验证,比不改还危险。

















