latch: cache buffers chains

latch: cache buffers chains

当一个数据块读入sga区,相应的buffer header会被放置到hash列表上,我们称其这hash chains,chain在中文的意为链条或串的意思,表达就是关连性.如果一个进程想访问或修改hash chain
上的block,它首先要获得”cache buffers chains” latch
 
 
latch: cache buffers chains 有2个原因:
原因一:低效率的SQL语句(主要体现在逻辑读过高)
 cache buffers chains latch很大程度与逻辑读有关,所以要观注v$sql中BUFFER_GETS/EXECUTIONS大的语句。
 同时每一个逻辑读需要一个latch get 操作及一个cpu操作,这样的sql也会很耗cpu资源。
 
原因二:热块(访问过于频繁)
--=======================================================
热点块的定义:极短的时间内对少量数据块进行了过于频繁的访问。
 
我们如何才能在大量的内存中迅速定位到自己想要的block?总不能去所有buffer中遍历吧!在此数据库引出了hash的概念(oracle中快速定位信息总是通过hash算法的,比如快速定位sql是
否在shared pool size中存在就是通过hash value来定位的,也就是说shared pool size中对象也是通过hash table来管理的),了解一点数据结构的基本知识就知道,hash 的一大重要功能
就是快速地查找。
 
oracle的block的管理。
oracle还提供了一种latch来保护这些block。因为要避免不同的进程随意地径直并发修改和访问这些block,这样很可能会破坏block的结构的。latch是数据库内部提供的一种维护内部结构的
一种低级锁,latch的生存周期极短(微秒以下级别),进程加latch后快速的进行某个访问或者修改动作然后释放latch(关于latch不再过多的阐述,那可能又是需要另一篇文章才能阐述清楚)
。这种latch数量是通过参数_db_block_hash_latches 来定义的,一个latch对应的保护了多个buckets。
一个latch大约可以维护128个左右的buffers。由于latch使得对block的操作的串行化(9i中有改进,读与读可以并行,但读与写、写与写依然要串行),很显然我们可以想到一个道理,如果大
量进程对相同的block进程进行操作,必然在这些latch上造成竞争,也就是说必然形成latch的等待。这在宏观上就表现为系统级的等待。明白了这些原理,为我们下面的在数据库中的诊断奠
定了基础。
--=============================================================
如何确定热点对象
 
如果我们经常关注statspack报告,会发现有时候出现cache buffer chains的等待。这个cache buffer chains就是_db_block_hash_latches所定义的latch的总称,
通过查询v$latch也可得到:
 
select latch#,name,gets,misses,sleeps from v$latch where name like 'cache buffer%';

    LATCH# NAME GETS MISSES SLEEPS
 150 cache buffers lru chain 3309248 452 18
 155 cache buffers chains 681949315 8721674 132191
 156 cache buffer handles 681 1 0

在这个查询结果里我们可以看到记录了数据库启动以来的所有cahce buffer chains的latch的状况,gets表示总共有这么多次请求,misses表示请求失败的次数(加锁不成功),而sleeps 表示
请求失败休眠的次数,通过sleeps我们可以大体知道数据库中latch的竞争是否严重,这也间接的表征了热点块的问题是否严重。由于v$latch是一个聚合信息,我们并不能获得哪些块可能存
在频繁访问。那我们要来看另一个view信息,那就是v$latch_children,v$latch_children.addr记录的就是这个latch的地址。

我们可以根据v$latch_child.addr关联到对应的x$bh.hladdr(这是buffer header中记录的当前buffer所处的latch地址),通过x$bh可以获得块的文件编号和block编号。
 
select dbarfil,dbablk
from x$bh
where hladdr in
 (select addr
from (select addr
from v$latch_children
order by sleeps desc)
where rownum < 11);

由此我们就打通了cache buffers chains和具体block之间的关系,那再继续下来,知道了block,我们需要知道究竟是哪些segment。这个可以通过dba_extents来获得。

找出热点块方法一:
 

--找出p1raw
select p1,p1raw from v$session_wait where event='latch: cache buffers chains';
--找到对象
SELECT /*+ RULE */ E.OWNER || '.' || E.SEGMENT_NAME SEGMENT_NAME, E.PARTITION_NAME, E.EXTENT_ID EXTENT#, X.DBABLK - E.BLOCK_ID + 1 BLOCK#, X.TCH, L.CHILD#  FROM SYS.V
$LATCH_CHILDREN L, SYS.X$BH X, SYS.DBA_EXTENTS E WHERE X.HLADDR = '00000002576EE018'--p1raw   AND E.FILE_ID = X.FILE#   AND X.HLADDR = L.ADDR   AND X.DBABLK BETWEEN
E.BLOCK_ID AND E.BLOCK_ID + E.BLOCKS - 1 ORDER BY X.TCH DESC;
 
到这里我们基本能找到热点块对对应的对象。但实际上还有另外一个途径来获取这些信息,那就是和x$bh.tch 相关的一种方法。对于8i开始oracle提供了接触点(touch count)来作为block是
冷热的标志,在一定条件满足的情况下block被进程访问一次touch count 增加一,到某个标准之后被移动到LRU热端(关于touch count 在这里不做详细介绍,那又将是一大篇文章)。那在短
时间内从某种意义上讲,touch count 大的block可能暗示着在当前某个周期内被访问次数比较多。
 
 

找出热点块方法二:
 
--直接找出热点块
SELECT OBJECT_NAME, SUBOBJECT_NAME  FROM DBA_OBJECTS WHERE DATA_OBJECT_ID IN       (SELECT DATA_OBJECT_ID          FROM (SELECT OBJ DATA_OBJECT_ID, FILE#, DBABLK,
CLASS, STATE, TCH                  FROM X$BH                 WHERE HLADDR IN (SELECT ADDR                                    FROM (SELECT ADDR                         
                  FROM V$LATCH_CHILDREN                                           ORDER BY (GETS + MISSES + SLEEPS) DESC)                                   WHERE
ROWNUM < 10)                 ORDER BY TCH DESC)         WHERE ROWNUM < 10);

到这里,我们寻找热点块和热点对象的工作算是完成了,但我们还并没有解决问题。

热点问题的解决
 
热点块和热点对象我们都找到了,但是我们该怎么来解决这个问题呢?一般来说,热点块会导致cache buffers chains竞争等待,但并不是说cache buffer chains一定是因为热点块而起,在
特别情况下有可能是因为latch数量的问题导致的,也就是一个latch管理的buffers数量太多而导致竞争激烈。但是latch数量我们一般是不会轻易去设置的,这是oracle的隐藏参数。
 
实际上最有效的办法,是从优化sql入手,不良的sql往往带来大量的不必要的访问,这是造成热点块的根源。比如本该通过全表扫描的查询却走了索引的range scan,这样将带来大量的对块
的重复访问。从而形成热点问题。再或者比如不当地走了nested loops的表连接,也可能对非驱动表造成大量的重复访问。那么在这个时候,我们的目标就是找出这些sql来并尝试优化。在
statspack报告中,根据报告中sql列表,我们如果是通过dba_extents确定的热点对象而不是通过dba_objects确定的,则可以通过查找出的热点segment转换为对应的表,对于非分区的索引,
index_name就是segment_name,通过dba_indexes很容易的找到对应的table_name,对于分区表和分区索引也能通过和dba_tab_partition和dba_ind_partitions找到segment和table的对应关系
。通过这些table到statspack报告中去找相关的sql。

除了优化sql外,当然对于热点的表或者索引来说,如果小的话,我们可以考虑cache在内存中,这样可能降低物理读提高sql运行速度(这并不会减少cache buffer chains的访问次数),对于
序列,我们可以对序列多设置一些cache。如果是并行服务器环境中的索引对象,并且这个索引是系列递增类型,我们可以考虑反向索引(关于反向索引这里就不过多地做介绍了)。
 
热点块的其他相关症状
 
在数据库中还可能存在一些其他方面的热点块症状,通过v$waitstat的等待可以看出一些端倪,v$waitstat是根据数据缓冲区中各种block的类型(x$bh.class)而分类统计的等待状况。

比如在ASSM表空间出现之前,由于freelist的存在,如果表经常被并发的进程DML,则可能存在大量的data block的等待,或者有free list的等待。那么这个时候我们发现这样的segment之后
需要考虑增加freelist数量。再比如经常发生长时间的DML的表被频繁地访问,这样将会造成过多的对回滚段中块的访问,这时可能undo block 的等待会比较多。那么我们可能需要控制DML的
时间长度或者想办法从应用程序入手来解决问题。如果是undo header的等待比较多,没使用undo tablespace 之前,可能需要考虑增加回滚段的数量。
 
 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/607244/viewspace-751216/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/607244/viewspace-751216/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值