在 Oracle 共享池(Shared Pool)中,Library Cache 是 SQL、PL/SQL、对象元数据等最核心的组件之一。当系统出现明显的 library cache lock 等待 时,通常意味着:
共享池中的对象访问、解析、失效或并发控制已经成为系统瓶颈。
本文从 内部原理 → 常见成因 → 定位方法 → 对应解决方案 → 风险评估 的角度,对 library cache lock 等待进行一次完整拆解。
一、Shared Pool 与 Library Cache Lock 的作用机制
共享池主要包含以下内容:
- Library Cache
- Data Dictionary Cache
- SQL Query Result Cache
- PL/SQL Function Result Cache
- Buffers for parallel execution messages
- Control structures
1. Library Cache Lock 的本质
library cache lock 用于控制多个客户端(Session)对同一对象的并发访问,它是:
- 在 对象句柄(object handle) 上获取的锁
- 用于保证:
- 某一时刻只有合法的访问者可以操作对象
- 对象在被依赖期间不被修改
其获取过程包括:
- 获取 library cache 子锁,扫描对象句柄列表
- 找到目标对象后,在句柄上放置 library cache lock
2. 它意味着什么?
- 一个 Session 正在:
- 解析 SQL
- 编译对象
- 执行依赖对象的 PL/SQL
- 另一个 Session 想:
- 使用同一对象
- 修改 / 失效该对象
此时就会产生 library cache lock 等待。
二、如何在报告中识别
library cache lock
1. TKProf
- Overall wait event summary
- non-recursive / recursive statements
- library cache lock 等待时间显著
2. AWR / Statspack
- Top Wait Events 中出现:
- library cache lock
- Library Cache Statistics 异常
三、常见成因一:SQL 因文字值无法共享(硬解析)
问题描述
SQL 本可使用绑定变量,却使用了字面量(literal),导致:
- SQL 无法共享
- 每次执行都触发 硬解析
- 频繁获取 library cache lock
定位方法
TKProf:
- 按 parse time 排序
- 检查:
- Misses in library cache ≈ Parse count
- 查找 SQL 中是否存在大量文字值
解决方案
重写 SQL,使用绑定变量
优点:
- 显著提升 SQL 共享率
- 降低硬解析与 library cache 争用
代价与风险:
- 费劲程度:中 / 高
- 风险:中
- 可能影响执行计划
- 必须充分测试
验证方式
- 实施后重新分析:
- AWR
- TKProf
- 若无改善:
- 重新确认是否为主要原因
四、常见成因二:共享池过小,已共享 SQL 被刷出
问题描述
- Shared Pool 太小
- 可共享 SQL 被频繁老化
- 再次执行 → 硬解析 → library cache lock
定位方法
AWR / Statspack:
- Library Cache Statistics:
- Reloads 很高(每小时几千)
- Invalidations 很少
- % SQL with executions > 1 > 60%
解决方案一:增大 Shared Pool
- 费劲程度:低
- 风险:低
- 除非物理内存不足
解决方案二(10g+):启用 ASMM
- 设置:
- SGA_TARGET
- SGA_MAX_SIZE
- 自动调节共享池大小
解决方案三:Pin 关键对象
- 使用:
DBMS_SHARED_POOL.KEEP()
- 保留:
- 大型
- 高频使用
- PL/SQL / Cursor
风险:
- 中度风险
- 过度 pin 可能引发 ORA-4031
五、常见成因三:Library Cache 对象失效(DDL / 统计信息)
1. DDL 导致失效
- CREATE / ALTER / DROP
- 级联失效依赖游标
- 引发大量硬解析
解决方案:
- 避免在繁忙期执行 DDL
- 安排到维护窗口
2. 收集优化器统计信息
- ANALYZE
- DBMS_STATS
影响:
- 对象失效
- 大量硬解析
解决方案:
- 避开高峰期
- 使用 no_invalidate(10g+)
3. TRUNCATE 操作
- 本质是 DDL
- 同样会引发对象失效
解决方案:
- 延后到低负载时段
六、常见成因四:跨 Session 编译对象
问题描述
- 一个 Session 编译对象(PL/SQL)
- 另一个 Session 正在执行 / 解析该对象
- 出现 library cache pin / lock 等待
定位方法
TKProf:
- library cache pin waits
- 伴随对象编译行为
解决方案
- 避免并发编译
- 避免高峰期编译
- 使用 HangAnalyze 定位阻塞链
七、常见成因五:开启审计(尤其 RAC)
问题描述
- 审计会增加 library cache lock 获取频率
- RAC 中影响更明显(全局资源)
定位方法
- AWR / Statspack:
- library cache lock waits
- 参数:
- audit_trail != none
解决方案
- 评估审计必要性
- 非强制合规场景可关闭
风险:
- 低风险
- 但需考虑合规要求
八、常见成因六:RAC 环境中的非共享 SQL
典型特征
- 单实例:表现为 latch 争用
- RAC:表现为 library cache lock
定位方法
- TKProf:
- 大量硬解析
- AWR:
- % SQL with executions > 1 < 60%
- Soft Parse Ratio < 80%
解决方案一:绑定变量
(同原因一)
解决方案二:CURSOR_SHARING 参数
- EXACT(默认)
- FORCE
- SIMILAR
建议:
- 优先 Session 级设置
- 避免 Instance 级 FORCE
风险:
- 中度风险
- 可能导致执行计划劣化
九、常见成因七:大量使用行级触发器
问题描述
- 行级触发器频繁触发
- 每次触发:
- 检查 mutating table
- 获取 library cache lock
关键点:
触发频率比触发器数量更重要
定位方法
- TKProf:
- 硬解析多
- recursive SQL
- trigger 相关痕迹
解决方案
- 评估是否必须使用行级触发器
- 设计替代方案
风险:
- 中度风险
- 需充分测试
十、常见成因八:过多的子游标(Version Count)
问题描述
- 单条 SQL 生成大量子游标
- 多 Session 并发创建 → 争用加剧
定位方法
- AWR:
- SQL ordered by Version Count
- V$SQLAREA.version_count > 500
- V$SQL_SHARED_CURSOR
常见诱因
- CURSOR_SHARING = SIMILAR
- 范围谓词(>、<)导致计划差异
解决方案选择
- 重写 SQL 使用绑定(最佳)
- 或改用 CURSOR_SHARING = FORCE(有风险)
十一、总结:排查
library cache lock
的正确姿势
一句话原则:
先判断是不是“非共享 SQL”,再判断是不是“对象失效或并发编译”,最后才考虑参数和内存。
实战顺序建议:
- TKProf 看解析
- AWR 看共享率 / Reload
- 排查 DDL / Stats / Compile
- 再谈参数调整
参考文档
-
‘library cache lock’ Waits: Causes and Solutions
Doc ID 1952395.1
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




