且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

oracle等待事件5——库高速缓存上的等待事件 上

更新时间:2022-08-22 10:41:52

1、latch:shared pool 锁存器

shared pool锁存器起到保护堆(共享池的基本内存结构)的作用,为了查找free chunk,检索空闲列,分配适当的chunk,必要时分割空闲chunk的一连串工作,全部只能在获得shared pool 锁存器后才能发生,获得shared pool锁存器的过程中若发生争用,则等待latch:shared pool事件。

与堆相关的一连串的工作大部分在非常短的时间内结束,因此一般情况下不出现shared pool 锁存器争用,但是如下情况,可能增加latch:shared pool 等待。

我的10g中查了一下,有7个shared pool latch(这是因为在9i以上的版本,oracle将共享池分为多个副池(sub pool),最多有7个副池分别进行管理,利用 _KGHDSIDX_COUNT隐含参数,可以管理副池,oracle在cpu为4,共享池大小在250M以上的情况下,通过创建与_KGHDSIDX_COUNT值相同量的副池来管理共享池,副池本身作为一个独立的共享池来管理,具有独立的空闲列,LRU列、shared pool 锁存器)。

如果hard parsing 严重时,经常发生分割chunk的现象,因此在空闲列上出现许多较小的空闲chunk的现象。这种现象称为共享池碎片化,因为共享池的碎片化,延长查询空闲咧的时间,相应拥有shared pool 锁存器的时间也会延长。共享池碎片化是引发shared pool 锁存器争用的根本原因。ora-4031错误也是由碎片化引发的。

在多个会话执行hard parsing 时,较多发生shared pool锁存器等待,因此在过多发生hard parsing的系统上,为了减少shard pool 锁存器等待,加大共享池大小是个非常愚蠢的做法,是的,非常愚蠢。为啥呢?你想啊,加大共享池,相应的空闲列数量和空闲列上需要管理的chunk数量也要增加。因此为检索空闲列拥有shared pool锁存器的时间也会延长。。latch:shared pool等待时间与其成正比增加。你会想,既然增加不行,那我减少吧。。。问题是,如果共享池大小减少,相应的空闲列上的空闲chunk的数量也会减少,所以检索空闲列所需的时间也会减少,但这时发生ora-4031错误的概率也就高了。可以位于共享池上的对象数量减少,可能引发hard parsing。为了消除这一点,可以利用dbms_shared_pool.keep procedure,应用将经常使用的sql cursor ,程序包,procedure 等永久的置于共享池。这个操作即便是使用alter system flush shard_pool也无法消除。


2、latch:library cache锁存器

library cache 锁存器与shared pool锁存器有着密切的关系。。例如,因执行sql 发生 hard parsing 时,oracle首先在获得library cache 锁存器状态下检索库高速缓存,在此状态下获得shared pool锁存器。在library cache锁存器获取阶段发生争用,而发生瓶颈现象时,latch:shared pool 等待就会出现的少。即便发生相同数量的hard parsing,多个会话同时执行parsing时,为寻找chunk 在获得shared pool锁存器之前,为了检索库高速缓冲区,在获得library cache 锁存器过程中发生争用。因此这时latch:library cache显得高,latch:shared pool 显得低。

我们大致可以这么理解,为了执行SQL,通过library cache 锁存器,保护检索并管理库高速缓冲区的所有工作;而为了寻找空闲的chunk,通过shared pool锁存器是吸纳保护扫描空闲列和分配适当chunk。。。

library cache 锁存器拥有比cpu count值大的最小质数值相同数量的子锁存器(child latch)。无哦一我的10g里面有3个。。嘿嘿。。

SQL> show parameter cpu_count


NAME                                 TYPE        VALUE
------------------------------------ ----------- ----------
cpu_count                            integer     2


SQL> select rownum,name,gets from v$latch_children where name='library cache';


    ROWNUM   NAME                                           GETS
----------        ---------------------------------------- ----------
         1       library cache                               2764635
         2       library cache                               1441963
         3       library cache                               1434052

在获得library cache 锁存器过程中,若发生争用,则等待latch:library cache 事件,library cahce 锁存器争用主要在如下情况下发生。

1)hard parsing 或soft parsing 过多:shared pool锁存器争用主要是因为hard parsing 引起的空闲列检索,与此相同,library cache 锁存器争用的最重要原因也是hard parsing 。若hard parsing 过多发生,就因如下原因引发了librarycache 锁存器争用。

第一:因为检索库高速缓冲区的次数增加,相应的拥有library cache 锁存器的时间和次数就会增加。

第二:hard parsing时,不仅需要对库高速缓冲区的查询,还需要进行额外的chunk 分配,因此相应的延长了拥有library cache 锁存器的时间。

从某种角度说,library cache 争用时比shared pool 锁存器争用更为严重的问题,因为shared pool 锁存器一般只在hard parsing 时发生,但是library cahce 争用在soft parsing时也会发生。虽然soft parsing 比hard parsing 耗费资源少,但是也不能避免语法语义的检查 / 库高速缓冲区检索过程。在这些过程中,检索库高速缓冲区期间必须获得library cache 锁存器。因此在许多会话同时执行soft parsing 时,会发生library cache 锁存器争用。


对于soft parsing 引发的library cache 锁存器争用,大致有两种解决方案:

***减少parsing次数,***的方法是一次parsing后执行数次,减少parsing次数,相应的library cache锁存器争用也随之减少。另外还要注意一点,使用PL/SQL的动态SQL时,可能会增加library cache锁存器争用。若使用了动态sql,则不能受益于PL/SQL优点中的一个cursor 重复使用效果(一次parsing 执行数次),因此soft parsing 会增加,library cache锁存器争用也会增加。使用静态sql ,可以只软解析一次。然后多次使用cursor。

*** 使用SESSION_CACHED_CURSORS参数:如果该值已经被设定,oracle就将已执行三次以上的sql cursor信息保存到PGA内,所保存的信息时 sql文本和对库高速缓冲区的指针。用户请求sql时,oracle将确认PGA上是否存在其信息。若存在,则立即向SGA相应的区域移动。因而,检索库高速缓冲区的时间减少。相应的拥有library cache 锁存器的时间也会随之减少。这个参数在我10g里缺省值是20,应该尽量设定为50以上的值。大师们说这种session cursor caching(会话游标缓存)功能称为 softer soft parse(更软的软解析)哈哈。在执行更软的软解析时,基本上与soft parsing做相同的工作。但是它是从pga中找sql语句和指向库高速缓冲区的指针,直接减少了对库高速缓冲区的检索。这也就减少library cache锁存器争用。


2)version count(sql语句的版本数量) 高时:假设,如下三名不同的用户执行相同的sql语句:

scott:select *  from emp where empno=1;

tom:select *  from emp where empno=1;

john:select *  from emp where empno=1;

这三个sql语句完全相同,所以具有相同的hash 值,因此被分配到相同hash chain 的相同句柄(handle)。但是emp表都是不同方案的表,所以实际上是不同的sql语句。这时,oracle将创建与文本(text)相应的父LCO,底下创建三个子LCO管理每个SQL信息。三个子LCO实际上存于匿名列(anonymous list 结构参考下图)。因具有三个子LCO,所以v$sqlarea视图的version_count列值与子LCO相同,是3。version_count的值高,也就意味着检索子LCO而导致检索库高速缓冲区的时间长。也就导致library cache 锁存器争用增加。

oracle等待事件5——库高速缓存上的等待事件 上

3)SGA区域发生page out 时:共享池已经向磁盘page out的时候,对该区域发生扫描时,重新将磁盘内容读取到内存过程中(page in)需要等待,因此对于library cahce锁存器的等待时间可能增加。


下面描述一下硬解析和软解析的定义:

先看一下步骤:

1)syntax检查(sql语句的语法检查);

2)semantic检查(语义,对象检查看看要操作的对象存不存在等);

3)权限检查(是否有权限对对象进行操作)

4)共享池的相同sql检索(利用hash值,检索库高速缓冲区,比较sql文本,相同对象的比较等)

5)创建parse tree(解析树)

6)创建执行计划。

通过执行1-4步骤,找到相同的sql语句的过程我们称为soft parsing(软解析),若是没有找到相同的sql语句,所以追加执行5-6过程称之为hard parsing(硬解析)