新博客http://www.cnblogs.com/zhjh256 欢迎访问
分类: Oracle
2008-01-06 21:56:19
很多DBA在评价数据库的性能时都花费一定的时间查看logical I/O,并将logical I/O作为CPU消耗的粗略指示。通常这是有道理的,但是由于某些原因有一定的误差。
一个重要的错误是Oracle可以通过不用执行logical I/O访问数据缓冲。
但是理解该问题的重要性前,必须明白logical I/O到底是什么,有两种可能的定义如下:一种是调用x$kcbwh中的子过程之一,另一种则是至少在cache buffers chains latch上得到一次。
但是如何确保在没有使用latch时访问一个缓冲块的安全呢—答案是你希望多次使用它(缓冲块),因此第一次使用latch得到它,然后在完成后释放latch,但是将其pin在临时地方,而不需要每次使用时都去竞争latch。
用来pin缓冲(实际上是缓冲头,而不是缓冲本身)的对象称为缓冲处理器(buffer handle)。
可用的缓冲处理器的数量依赖于启动时的设置,并且依赖于进程的数量--5 * processes。默认通常为5,由_db_handles设置。这些处理器存储在x$kcbbf结构中。
为了pin缓冲头,会话必须首先得到一个缓冲处理器,完成该动作的第一步是争夺cache buffer handles latch保护x$kcbbf数组的完整性。当然,如果会话每次想要pin缓冲时都必须争夺该latch,那么这种latch将会成为主要的冲突。因此允许每个会话建立一个小的保留集或者称 处理器(handle)缓存。会话不需要得到latch使用,并重用这个小的处理器集。
当然某些查询可能会相当复杂,并且如果可以pin大量的缓冲,操作将会非常有效。因此如果有更多的空闲处理器可以使用,会话将允许得到多于5个的处理器。因此一个会话允许的最大处理器数为db_block_buffers / processes,在使用动态缓存时该算法会有一定的问题。该限制以_cursor_db_buffers_pinned参数发布。
缓冲pin的代价和效率可以通过两个统计查询:buffer is pinned count,该统计报告访问一个缓冲而不需要得到latch的次数;no buffer to keep pinned count,表示当希望pin一个缓冲的时候,或者超出了限制,或者在数组中找不到空闲的pin。
第一个统计是会话完成的工作的度量,第二个则表明processes相对于缓冲缓存太大,或者反之,db_block_buffers太小。
某些注意点
缓冲只能在调用期间被pin,在调用结束后必须被释放。
如果缓冲被pin住,它们将不能从内存中被刷新出去—即使出现在lru的尾端。
缓冲(缓冲头)可以在排斥模式被pin,也可以在共享模式。如果使用排斥模式pin(x$bh.mode_held),其他会话需要将它们的pin附属到缓冲头的'waiters list'上,然后进入'buffer busy waits'状态。
大多数缓冲get要求得到两个latch—一个用于定位和pin缓冲,另一个用于unpin缓冲;但是也有一些只需要一个latch(由consistent gets – examination报告)并在保持latch期间查看缓冲。主要包括:读取索引的根块,创建一致性读时读取撤销块,读取单表哈希中的单块(除非设置了'collision flag'标记)。
得到Latch是非常耗费cpu的,因此Oracle内核不断的改进以增加缓冲可以pin的代码点数量。最常pin的缓冲是用来范围扫描的索引页块。
相关的参数
_db_handles_cached:默认5;
_db_handles:processes * _db_handles_cached;
_cursor_db_buffers_pinned:db_block_buffers / processes – 2
_session_kept_cursor_pins
相关的统计
Buffer is pinned count:避免gets的测量;
No buffer to keep pinned count:表示相对于db_block_buffers,processes太大。
相关的latch
cache buffers chains latch—减少活动;
cache buffer handles latch—保护处理器数组;
相关的内核结构
x$kcbbf—缓冲处理器的数组;
x$bh缓冲头;