enq:Library cache lock/pin等待事件

前言:ORACLE数据库内存两个很重要的部分:Buffer cache和Library cache,早期已经有整理过一篇关于Buffer cache的管理和关于Buffer cache的等待事件(cache buffers chains),一直想整理一篇关于Library cache的文章,刚好在oracle的官网上看到了相应的文档,顺手记录下来,供大家参考。

(library cache的文档http://www.hellodb.net/2010/07/oracle-library-cache.html)

1、什么是Library cache lock

这个事件控制对 library cache 的并发使用。 它获取一个对象句柄(object handle)上的锁,从而:

  • 一个使用者可以防止其它使用者访问同一个对象。
  • 这个使用者可以长时间地维护一个依赖对象(例如,其它使用者不能更改这个对象)。

定位 library cache 中的一个对象同样也需要这个锁。
在解析或编译 SQL 或 PL/SQL 语句期间,我们需要获得被引用的数据库对象(表,视图,过程,函数,包,包体,触发器,索引,聚簇,同义词)的 library cache lock;这个锁在解析与编译结束时会被释放。

cursor(SQL 与 PL/SQL 区),管道(pipes)和其它的瞬时(transient)对象不使用这个锁。

Library cache lock 上的死锁不会被自动检测到,对其的操作是同步进行的。

参数:

  • handle address:对象地址;
  • lock address:锁地址。它与 latch 与 enqueue 不同,它是一个 State Object;
  • Mode:申请锁的级别;
  • Namespace:对象使用的 namespace, 取自于 V$DB_OBJECT_CACHE。

2、什么是"Library cache pin" 

这个事件管理 library cache 并发。Pin 住一个对象会使它使用的 heap 被载入到内存中。如果一个使用者想要修改或检查这个对象,它必须在获得 lock 之后再取得一个 pin。Pin 可以用 NULL, SHARE, EXCLUSIVE 模式获得,并且可以看做是一种特殊的 lock。等待"library cache pin"意味着这个 PIN 正被某个其它 session 以不兼容的模式持有。
访问当前被缓存到 library cache 中的数据库对象(表,视图,过程,函数,包,包体,触发器,索引,聚簇,同义词)的时候需要获得 library cache pin; 在 library cache 中,数据库对象被缓存成两部分:句柄(handle)和对象(object); 这个锁(pin)是用来保护"object"部分的。
Library cache pin 上的死锁不会被自动检测到,对其的操作是同步进行的。
注意:在10g以后,"library cache pin"已经被 mutex 取代。
参见:Note 1298015.1 WAITEVENT: "cursor: pin S wait on X" Reference Note

3、为什么需要这两种不同类型的锁

       Lock 与 pin 都用于访问在 library cache 中的对象。Lock 管理不同进程间的并发,pin 则管理缓冲区的一致性。为了访问一个对象,进程必须首先锁定(lock)这个对象的句柄(handle),然后它自己 pin 住对象的内存堆。Lock 与 pin 请求会一直等待直到获得为止,这是一个引起争用的可能的原因,因为它没有 NOWAIT 请求模式。通过获得一个在对象句柄上的锁,一个进程能防止其它进程访问这个对象,甚至不可以查看它的类型。它还能在维护对象依赖关系的同时不阻止其它进程访问这个对象。获取一个 lock 同样也是在缓存中查找对象的唯一途径。查找并锁住对象是在一个操作中完成的。如果一个进程想检查或修改一个对象,那么它必须获得一个在这个对象上的 pin (获得了在句柄上的锁之后)。Pin这个动作会将相应对象的信息载入到内存,如果之前没有的话,同时还能确保这些信息保留在内存直到 pin 被释放。

       Oracle 在分析/编译 Package/Procedure/Function/View 时需要 Library Cache Lock 和 Library CachePin。这是为了确保在分析/编译期间, 没有其它人可以对这些对象的定义进行改变,或者删除、重建这个对象。

当一个 SQL 语句被一个 session 硬解析时,这个 session 需要获得一个 library cache lock 以便阻止其它 session 去访问或修改同一个对象。如果这个事件等待很长时间。这表明可能 shared pool 过小或经常

发生对象被 flush 出去的清醒。还有,这表明数据库对象被经常修改。除了硬解析,如果一个 session 要更改被 SQL 语句引用的对象的定义或对其做任何更改,就必须获得一个library cache lock 和 library cache pin。需要 Pin 的原因是需要加载数据字典信息到内存中来修改这个对象。

4、减少Library Cache 竞争的一般建议

下边会介绍一下解决不同竞争的不同的方法。但是,很多时候这些现象都是由于 SQL 语句的版本数造成的。如果您看到了任何跟 library cache 相关的竞争,应该立刻检查 AWR Report 确保没有版本数很高(比如几百)的 SQL 语句。

enq:Library cache lock/pin等待事件

5、如何降低 library cache lock 等待

我们首先要确认的是 library cache 的竞争是整个系统层面的还是只发生在某个或某些 SQL 语句上。这个"library cache lock"是被一个特定的 SQL 持有很长的时间吗?或者总是在等待某个特定的对象?还是说这个锁在短时间内被请求的次数很多从而造成的竞争?
如果问题是在整个系统层面发生的,一般来说是由于 shared pool 太小或 SQL 语句不共享造成的。一些解决竞争的方法:

  • 增大 shared pool 从而减少 reload 的次数,这是因为 shared pool 过小会造成获取锁的时间加长。
  • 通过将 cursor_sharing 设置为 similar 或 force 来使 SQL 语句共享。(需要小心的是这样做可能会改变SQL的执行计划,所以做之前需要做完整的测试)
  • 在系统不繁忙的时候做统计信息的收集或其它维护作业,从而降低无效化(invalidation)的次数。

如果您发现是某条或某些SQL产生的问题,那么需要检查为什么它持有锁的时间会那么长。

https://support.oracle.com/epmos/faces/DocumentDisplay?parent=DOCUMENT&sourceId=1548524.1&id=122793.1

6、如何降低 library cache pin 等待

如果"library cache pin"等待的时间很长那么很重要的一点就是判断是只有一两个 process 在等待还是有很多的 process 都在等待。

  • 如果说只是一两个 process 被另一个 process 阻塞的话,那么需要检查持有这个 pin 的process 为什么这么长时间不释放。
  • 如果说等待是大范围的那么说明 shared pool 需要优化。

https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=201008601673047&parent=DOCUMENT&sourceId=1548524.1&id=62143.1&_afrWindowMode=0&_adf.ctrl-state=12aq9613b9_94

总结:以上都是解决问题的理论基础,具体还得在真正的生产环境中解决了问题,才算是真正的掌握了问题,接下来希望能为大家整理一篇实战的过程的文档。

*********************************************************************************************************

本文作者:JOHN QQ:1916066696 (请备注数据库)

ORACLE技术博客:
ORACLE 猎人笔记 http://blog.itpub.net/12679300/

*********************************************************************************************************

上一篇:[IOS]自定义长触屏事件


下一篇:AliOS Things v1.1.2新特性