buffer cache 深入 latch

本文深入探讨了Oracle数据库中的Latch机制,包括Latch的工作原理、如何引起Latch争用及其解决办法。文章还详细介绍了buffer cache相关的等待事件,如latch free,并提供了诊断和优化的相关SQL查询。

  _db_block_hash_buckets  Number of database block hash buckets   8比1  8000对1000 那样

_db_block_hash_latches    cache buffers chains latch                           8比11

等待latch 的原因

1 我就1000latch 你过来几万个块要找,肯定要等待

2.你们老是找我这个latch 管理下的块 我这一个latch就很忙。

buffer cache的等待事件
    与buffer cache相关的等待事件包括:latch free、buffer busy waits、free buffer waits。曾经发生过的等待事件可以从v$system_event(一个等待事件对应一行记录)和v$session_event(一个session一个等待事件对应一行记录)中看到。而当前系统正在经历的等待事件可以从v$session_wait看到。

latch free等待
       等待事件“latch free”中与buffer cache有关的有两类:cache buffers chains latch和cache buffers lru chain latch。在理解了上面所描述的有关buffer cache的内部管理机制以后,就应该很容易理解这两个latch产生的原因。

    对于buffer cache中的每个hash chain链表来说,都会有一个名为cache buffers chains latch的latch来保护对hash chain的并发操作,这种latch通常也叫作hash latch或CBC latch。数据库中会有很多的cache buffers chains latch,每个latch都叫做child cache buffers chains latch。一个child cache buffers chains latch会管理多个hash chain。前面我们知道,hash chain的数量由一个隐藏参数:_db_block_hash_buckets决定。同样也有一个隐藏参数:_db_block_hash_latches来决定有多少个cache buffers chains latch来管理这些hash chain。该参数的缺省值由buffer cache中所含有的内存数据块的多少决定,当内存数据块的数量
     •少于2052个时,_db_block_hash_latches = power(2,trunc(log(2, 内存块数量 - 4) - 1))
    •多于131075个时,_db_block_hash_latches = power(2,trunc(log(2, db_block_buffers - 4) - 6))
    •位于2052与131075 buffers之间,_db_block_hash_latches = 1024
可以使用下面的SQL语句来确定当前系统的cache buffers chains latch的数量。

 SQL> select count(distinct(hladdr)) from x$bh; COUNT(DISTINCT(HLADDR)) -----------------------  1024 SQL> select count(*) from v$latch_children where name='cache buffers chains';  COUNT(*) ----------  1024

     在知道了cache buffers chains latch的数量以后,我们只需要用hash chain的数量除以latch的数量以后,就可以算出每个latch管理多少个hash chain了。我们将下面7532除以1024,就可以知道,当前的系统中,每个latch大概对应8个hash chain。

 SQL> select x.ksppinm, y.ksppstvl, x.ksppdesc  2 from x$ksppi x , x$ksppcv y where x.indx = y.indx and x.ksppinm like '\_%' escape '\'  and ksppinm like '%_db_block_hash_buckets%' ; KSPPINM KSPPSTVL KSPPDESC ---------------------- -------- ------------------------------------- _db_block_hash_buckets 7523 Number of database block hash buckets

    当数据库在hash chain搜索需要的数据块时,必须先获得cache buffers chains latch。然后在扫描hash chain的过程中会一直持有该latch,直到找到所要的数据块才会释放该latch。当有进程一直在扫描某条hash chain,而其他进程也要扫描相同的hash chain时,其他进程就必须等待类型为cache buffers chains latch的latch free等待事件。

    不够优化的SQL语句是导致cache buffers chains latch的主要原因。如果SQL语句需要访问过多的内存数据块,那么必然会持有latch很长时间。找出逻辑读特别大的sql语句进行调整。v$sqlarea里那些buffer_gets/executions为较大值的SQL语句就是那些需要调整的SQL语句。这种方式不是很有针对性,比较盲目。网上曾经有人提供了一个比较有针对性的、查找这种引起较为严重的cache buffers chains latch的SQL语句的方式,(按sleep排序为什么)其原理是根据latch的地址,到x$bh中找对应的buffer header,x$bh的hladdr表示该buffer header所对应的latch地址。然后根据buffer header可以找到所对应的表的名称。最后可以到v$sqltext(也可以到stats$sqltext)中找到引用了这些表的SQL语句。我也列在这里。where条件中的rownum<10主要是为了不要返回太多的行,只要能够处理掉前10个latch等待就能有很大改观。

 select /**//*+ rule */ s.sql_text from x$bh a,dba_extents b, (select * from (select addr from v$latch_children  where name = 'cache buffers chains' order by sleeps desc) where rownum<11) c, v$sqltext s where a.hladdr = c.addr  and a.dbarfil = b.relative_fno  and a.dbablk between b.block_id and b.block_id + b.blocks  and s.sql_text like '%'||b.segment_name||'%' and b.segment_type='TABLE' order by s.hash_value,s.address,s.piece /

----sleep的原因

Latch相关的视图--V$LATCH 用来查看latch争用情况,系统级别的问题定位

当如果misses次数比较大说明获取latch资源的会话很多,那么可能发生了latch争用。

--------- 

    还有一个原因可能会引起cache buffers chains latch,就是热点数据块问题。这是指多个session重复访问一个或多个被同一个child cache buffers chains latch保护的内存数据块。这主要是应用程序的问题。大多数情况下,单纯增加child cache buffers chains latches的个数对提高性能没有作用。这是因为内存数据块是根据数据块地址以及hash chain的个数来进行hash运算从而得到具体的hash chain的,而不是根据child cache buffers chains latches的个数。如果数据块的地址以及hash chain的个数保持一致,那么热点块仍然很有可能会被hash到同一个child cache buffers chains latch上。可以通过v$session_wait的p1raw字段来判断latch free等待事件是否是由于出现了热点块。如果p1raw保持一致,那么说明session在等待同一个latch地址,系统存在热点块。当然也可以通过x$bh的tch来判断是否出现了热点块,该值越高则数据块越热。

 SQL> select sid, p1raw, p2, p3, seconds_in_wait, wait_time, state  from v$session_wait  where event = 'latch free'  order by p2, p1raw;  SID P1RAW P2 P3 SECONDS_IN_WAIT WAIT_TIME STATE ---- -------- --- --- --------------- ---------- ------------------  38 6666535C 13 1 1 2 WAITED KNOWN TIME  42 6666535C 13 1 1 2 WAITED KNOWN TIME  44 6666535C 13 3 1 4 WAITED KNOWN TIME ………………………  85 6666535C 13 3 1 12 WAITED KNOWN TIME  214 6666535C 138 1 1 2 WAITED KNOWN TIME

接下来,我们就可以根据p1raw的值去找到所对应的内存数据块以及对应的表的名称了。

 select a.hladdr, a.file#, a.dbablk, a.tch, a.obj, b.object_name from x$bh a, dba_objects b where (a.obj = b.object_id or a.obj = b.data_object_id) and a.hladdr = '6666535C';
 

-------latch

Latch在数据库层里面业务层面是看不到的,不像锁是可以感知到的,比如一个会话被谁锁定了被谁阻塞住了。

�LOCK
– enqueue:队列,其实就是锁,也就是业务层面的阻塞。enqueue实际上就是队列,要求进程排队使用资源的会话排队
–latch

Latch的目的

�保证资源的串行访问:
– 保护SGA的资源访问
– 保护内存的分配
�保证执行的串行化:
– 保护关键资源的串行执行
– 防止内存结构损坏

Latch是保护数据库本身的内存结构,不是业务层面的保护

Latch V.S. enqueue

Latch不具有队列性,是大家争先恐后的去申请资源,混乱的。enqueue是队列性的,只能等到资源释放了才可以拿到资源,如果没有释放那么只能等着,等释放之后才能拿到锁。

Latch在哪里?---SGA

资源的请求和分配
�共享池
– sql 解析,sql重用....
�数据缓冲池
– 数据访问,数据写入磁盘,数据读入内存...
– 修改数据块
– 数据段扩展

Latch不在PGA里面,PGA不是共享的资源,SGA主要分为两块共享池和数据缓冲池。

Oracle有哪些Latch

Latch的机制

在SGA区里面有一个Latch,这个时候process A获得了一个Latch,获得了Latch就开始干活消耗cpu了,这个时候process B也去尝试获得这个Latch,但是未成功,因为进程A以及持有这个Latch了,这个时候就出现等待了,这个等待就是Latch的获取

Latch的的获取

� wait方式--如果无法获取请求的latch,则:
– spin
• 当一个会话无法获得需要的latch时,会继续使用CPU(CPU 空转),达到一个间隔后,
再次尝试申请latch,直到达到最大的重试次数。
– sleep
• 当一个会话无法获得需要的latch时,会等待一段时间(sleep),达到一个间隔后,再次
尝试申请latch,如此反复,直到达到最大的重试次数。
� No wait方式--如果无法获取请求的latch,则:
– 不会发生sleep或者spin.
– 转而去获取其它可用的Latch

Latch持有的时间是非常短的,当一个会话去申请Latch的时候恰好有别人在用的时候,当第二次去申请的时候几乎就会成功了,因为获得cpu首先就要去申请cpu,频繁的申请cpu还不如一直持有cpu让cpu空转。

shared pool里的latch争用--绑定变量(share pool里面是对SQL方面进行争用,buffer cache里面的是对数据块的争用)

绑定变量和没有绑定变量对latch的争用。

p1存储过程是没有使用绑定变量的。P2存储过程是做了绑定变量

两个存储过程执行完毕后的对比,run1是没有使用绑定变量的存储过程,run2是使用了绑定变量的存储过程。可以看到run2消耗的资源远小于run1消耗的资源。可以看出绑定变量相对于不绑定变量对share pool消耗大大减小了。 真的是差距太大了。。


 

V$SESSION_EVENT 和 V$SYSTEM_EVENT 

V$SESSION 及 V$SESSION_WAIT 视图记录了活动会话当前正在发生的等待 , 但 是 要 知 道 一 个 活 动 会 话 在 其 生 命 周 期 只 能 可 能 经 历 很 多 等 待 , 这 些 等 待 通 过V$SESSION_EVENT 视图记录。但是需要注意的是,这个视图记录的是累积信息,同一会话对于同一事件发生的多次等待会被累计。以下是一个会话的等待事件输出: 

V$SESSION_EVENT 的 信 息 和 会 话 生 命 周 期 相 关 , 这 些 信 息 同 时 会 被 累 积 到V$SYSTEM_EVENT 视图作为数据库整体等待数据保存,比如:

但是注意, V$SESSION_EVENT 或者 V$SYSTEM_EVENT 视图的累积信息以及关于等待的平均计算,使我们无法得知个别等待消耗的时间长短。
为了解决这一问题, Oracle 10g 引入了一个新的视图 v$event_histogram,通过这个视图可以看到等待事件的柱状图分布,从而可以对一个等待事件的具体分布有进一步的了解,在以下查询输出中可以看到, Shared Pool Latch 的竞争主要是 10 毫秒以内的短时竞争,但是注意等待时间在 256 毫秒左右的等待也有 5 次,长时间的 Latch 竞争是在数据库优化时需要认真关注的:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值