cache buffers chains ,buffer busy waits

 当一个session想要访问/修改buffer cache的block,首先需要检查该block是否存在于buffer cache,检查该block是否存在于buffer cache中是通过HASH算法来实现的,另外检查相同的SQL语句是否存在于library cache中也是通过HASH算法实现的。要判断block是否存在于buffer cache中,就需要扫描一条chain,该chain中具有block的信息。而扫描这个chain必须获得一个latch,防止并发对chain照成破坏,如果未能获得该latch,就说明此block是hot block,同时在数据库中标记一个latch: cache buffers chains这个等待事件。如果该block存在于buffer cache中就不需要物理读,如果不存在,就需要物理读取该block到buffer cache中。为了能够读取,并修改该block,我们就需要pin住该block,防止并发对于该block造成破坏,所以如果别的session不能获得pin,Oracle就会标记一个buffer busy waits等待事件。

 注意,在10g中,如果一个session等待另外一个session读取该block,会提交一个read by other session等待事件,下面是来自10gR2的查询。

SQL> select event#,event_id,name from v$event_name where name like '%read by%';

    EVENT#   EVENT_ID NAME
---------- ---------- ----------------------------------------------------------------
        67 3056446529 read by other session
而在10g之前会提交buffer busy waits等待事件,在10g之后,buffer busy waits表示一个session等待另外一个session完成对block的修改。

      当出现了比较严重的cache buffers chains竞争时,我们可以找出该热点块的具体对象,找出引起该竞争的SQL语句,修改不良的SQL。如果不能更改应用,可以尝试将数据分散,设置高的pctfree,使用较小的block size,查看SQL执行计划是否正确,减少逻辑读,如果CPU负载不是很高可以尝试修改_spin_count,或者增加hash bucket的数量。注意,修改_spin_count,hash bucket一定要仔细斟酌。

      当出现了比较严重的buffer busy waits是,我们可以通过如下查询初步判断是哪些block引起了竞争。

  SQL> select * from v$waitstat where count>0;

CLASS                                                       COUNT       TIME
------------------------------------------------------ ---------- ----------
undo header                                                    18          1
      同样我们可以关联v$session_wait,v$session,v$sqlarea视图找出引起该竞争的SQL语句,通过p1,p2,p3查找该竞争所属的对象类型,对象拥有者等等。

     

你可能感兴趣的:(sql,算法,cache,session,buffer,library)