【学习笔记】理解Library Cache及相关等待事件

Library Cache及相关等待事件

一、Library Cache结构

​ Library Cache(库缓存)的结构就是一张有多个Hash Bucket组成的Hash Table,而在Hash Bucket中,则存放了相同Hash值的所有Library Cache Object Handle(库缓存对象句柄),这些句柄之间是由链表连接起来的,形成了库缓存对象句柄链(Library Cache Object Handles)。

Library Cache —> Hash Table —> Hash Bucket —> Library Cache Object Handles —> Library Cache Object Handle

在这里插入图片描述
在Library Cache Object Handle中,则保存了具体对象的相关属性,包括名称、命名空间、lock信息、pin信息、标记以及对象内存地址指针(heap0)。

​ 而heap 0中则保存了该对象的名字、类型、该对象依赖对象表信息、子对象(比如不同的子游标)、对象授权信息、以及对象的真实数据存储内存指针信息(Data Blocks —> Data Heap,而Data Heap则包括了SQL语句、执行计划、执行文本等信息)。
在这里插入图片描述

​ LIBRARY CACHE的对象可以在V D B O B J E C T C A C H E 中 找 到 , 这 个 视 图 基 于 X DB_OBJECT_CACHE中找到,这个视图基于X DBOBJECTCACHEXKGLOB

二、Library Cache作用

1.作用概要

​ Library Cache主要作用就是缓存执行果的SQL语句和PL/SQL语句包含的对象、依赖对象、子游标以及包含的执行计划、解析树等对象。

如果相同的SQL语句和PL/SQL语句再次被执行时,就可以利用已经换存在Library Cache中的那些相关对象而无需再次从头开始解析,从而提高这些SQL语句和PL/SQL语句在重复执行时的执行效率。

2.SQL访问解析过程

​ 当客户端发起一条SQL语句或PL/SQL语句的执行时,Oracle会先将该SQL语句或PL/SQL代码块转换为ASCII数值,然后对这些ASCII数值进行hash运算,从而生成hash值,然后去和library cache中的Hash Bucket,然后再去匹配Hash Bucket上面Object Handler:

如果匹配成功则会去找child cursor,当找到child cursor后则直接执行(软解析); 如果子游标被交换出library cache,那么通过父游标信息重新构造reload一个child cursor(硬解析);

如果匹配失败,即不存在共享的父游标,就会在library cache中分配一些内存(Chunk),并将新产生的父游标保存进library cahce,然后生成一个Object的handle(对象句柄),挂载hash bucket上(硬解析)。

附加:

​ 软软解析(Soft Soft Parse)是指若参数SESSION_CACHED_CURSORS的值大于0,并且该会话游标所对应的目标SQL解析和执行的次数超过3次,则此时该会话游标会被直接缓存在当前会话的PGA中的。若该SQL再次执行的时候,则只需要对其进行语法分析、权限对象分析之后就可以直接从当前会话的PGA中将之前缓存的匹配会话游标直接拿过来用就可以了,这就是软软解析。

三、Library Cache等待事件

Library Cache Lock/Pin

​ 从Library Cache的Hash Bucket中的Object Handler的结构中可以看到,Object Handler中除了存储对象信息外,还会存储该对象的lock信息和pin信息。Lock信息和pin信息是用于控制Oracle对Library Cache中的Object做的并发访问的(Lock管理并发pin管理一致性),其中Lock是针对handle的,而pin则是针对heap的。因此,Library Cache中则会产生两个常见的等待事件:

Library Cache Lock

Library Cache Pin

针对这两个等待事件的触发器主要有四个场景:

SQL —> get library cache lock —> get library cache pin

​ 1.当我们通过sql想要访问某个library cache object的时候,我们就要首先获得这个指向这个object的handle的lock,获得这个lock之后我们就需要pin住指向这个object的heap;

​ 2.当我们对包,存储过程,函数,视图进行编译的时候,Oracle就会在这些对象的handle上面首先获得一个library cache lock,然后再在这些对象的heap上获得pin,这样就能保证在编译的时候其它进程不会来更改这些对象的定义,或者将对象删除。

​ 3.当一个会话对SQL进行硬解析的时候,这个session则必须获得sql相关对象的library cache lock,这样做主要就是为了防止其他会话访问或者更改这个SQL引用的对象(如果硬解析花费时间过长,则可能是共享池太小,需要搜索free的chunk或者将某些可以被移出的object page out)。

​ 4.当一个会话正在对相关对象(表)做出修改(比如分区、修改字段等),当前的会话需要引用那个table,这种情况下我们必须等另外的会话执行完毕。

Library Cache Lock有三个模式:

SHARE:在我们需要读取一个Library Cache Object的时候,获取的Library Cache为Share模式,比如我们编译某个视图的时候,就会对相关对象获取一个共享锁;

EXCLUSIVE:在我们需要修改一个Library Cache Object的时候,获取的Library Cache为Exclusive模式,比如我们要对某个对象做create、drop、alter等操作的时候,就会得到一个独占锁;

NULL:作为一个标记锁,可以标记对象为有效;任何可以执行的对象(cursor,function)上面都拥有NULL锁,我们可以随时打破这个NULL锁,当这个NULL锁被打破了,就表示这个对象被更改了,需要从新编译。

Library Cache Pin有两个模式:

Share : 读取object heap

Exclusive(X):修改object heap

需要注意的是:在获得pin之前必须获得lock。

Library Cache Latch :

Library cache latch,是用来控制对library cache object的并发访问。前面已经提到,我们要访问library cache object之前必须获得library cache lock, lock不是一个原子操作(原子操作就是在操作程中不会被打破的操作,很明显这里的lock可以被打破), Oracle为了保护这个lock,引入了library cache latch机制,也就是说在获得library cache lock之前,需要先获得library cache latch,当获得library cache lock之后就释放library cache latch。

SQL —> get library cache latch —> get library cache lock —> get library cache pin

​ 如果某个library cache object没有在内存中,那么这个lock就不能被获取。这个时候需要获得一个library cache load lock latch,然后再获取一个library cache load lock,当load lock获得之后就释放library cache load lock latch。

SQL —> get library cache load lock latch —> get library cache load lock —> releas library cache load lock latch

​ 注:library cache latch受隐含参数KGL_LATCH_COUNT的控制,默认值为大于等于系统中CPU个数的最小素数,但是Oracle对其有一个硬性限制,该参数不能大于67。我们去查询kgl_latch_count有时候显示为0,这是一个bug。

四、通过SQL查找library cache的相关信息

1.X$KGLLK表

该基表中包含所有library object locks的信息(held和requested),主要有以下几列:

KGLNAOBJ 列包含了在librarky cache中的对象上执行命令的语句的前80个字符,其实从这里我们也可以大大缩小范围了
KGLLKSES 对应于V$SESSION 中的 SADDR列的值
KGLLKSNM 对应于V$SESSION 中的SID(Session ID)
KGLLKHDL 的值对应'handle address'的值;
KGLLKPNS 的值对应'Ssession pin'的值
KGLLKREQ 的值显示了这个该会话请求的library cache锁

2.查看等待事件为library cache lock的session 的session address (SADDR)

select sid,saddr from v$session where event='library cache lock';

3.从x$kgllk查看具体的锁信息

select kgllkhdl Handle, kgllkreq Request,kglnaobj Object from x$kgllk
 where kgllkses = '&saddr'
   and kgllkreq > 0;

4.根据KGLLKHDL从X$KGLLK查看KGLLKMOD > 0的session,其正在持有该锁

select kgllkses saddr, kgllkhdl handle,kgllkmod mod, kglnaobj object from x$kgllk 
lock_a 
where kgllkmod > 0 and exists 
(select lock_b.kgllkhdl
          from x$kgllk lock_b
         where kgllkses = '&saddr'
           and lock_a.kgllkhdl =lock_b.kgllkhdl
           and kgllkreq > 0);

5.查看所有blocked的session

select sid, username,terminal, program from v$session 
where saddr in
(select kgllkses from x$kgllk lock_a
 where kgllkreq > 0 and exists 
 (select lock_b.kgllkhdl from x$kgllk lock_b
  where kgllkses = '&saddr'
  and lock_a.kgllkhdl =lock_b.kgllkhdl
  and kgllkreq = 0));

6.查看锁有持有library cache pin 或者lock的session在做什么

SELECT s.sid, kglpnmod "Mode",kglpnreq "Req", SPID "OS Process"
  FROM v$session_wait w,x$kglpn p, v$session s, v$process o
 WHERE p.kglpnuse =s.saddr
   AND kglpnhdl = w.p1raw
   and w.event like'%library cache %'
   and s.paddr = o.addr;

猜你喜欢

转载自blog.csdn.net/wx370092877/article/details/125165130
今日推荐