简单来讲,Oracle为了高效管理BUFFER CACHE主要使用以下2种LRU列: LRU列,又叫替换列(replacement list),其中又分为主列和辅助列。 主列:已使用的缓冲区列,分为HOT和COLD区域。HOT区域中存放着使用频率高的数据块,COLD区域存放使用频率较低的数据块。Oracle用TCH表示该区域内数据块的使用频繁程度。 辅助列:空闲缓冲区列。数据库重启之后,所有的缓冲区头开始时都是在辅助列中管理的。或者在LRU-W上的脏数据写进制数据文件之后,Oracle会将相关的缓冲区头直接挂载至辅助列上。辅助列上的缓冲区头表示可以直接被其他数据块使用。 LRU-W列,又叫写入列(LRU-Write list),脏数据列。脏缓冲区头由DBWR进程从LRU列移动至LRU-W列中(有时DBWR进程因为太忙而不能执行这种移动)。寻找空闲缓冲区的服务器进程在LRU列表上扫描时,如果遇到了脏缓冲区头,就将脏缓冲头从LRU列表中移动至LRU-W列表中。LRU-W列中又分为主列和辅助列。 主列:已修改的缓冲区列。 辅助列:当前正通过DBWR进程写入的缓冲区列。 提示 除了LRU列和LRUW列,还有LRU-XO列、LRU-XR列、LRU-P列。在性能优化时,最容易引起性能问题的是LRU列和LRU-W列,所以一般情况下并不需要关心LRU-XO列、LRU-XR列、LRU-P列,所以本章也不打算深入讲解这3列。 LRU列和LRW-W列总是成对(pair)的出现,称之为WORKING SET。为了提高性能,Oracle使用多个WORKING SET,由CACHE BUFFERS LRU CHAIN LATCH保护。基于性能上的考虑,服务器进程在检索空闲缓冲区时,首先会检索LRU列的辅助列,当辅助列没有剩余缓冲区时,才会检索LRU主列中的COLD区域。 另外需要指出的是LRU列中HOT和COLD区域只是针对nK BUFFER POOL的,KEEP POOL和RECYCLE POOL中没有HOT和COLD区域之分。KEEP POOL比较适合存放使用频繁读取的小表,RECYCLE POOL比较适合存放使用频率较低的大表。数据块在nK BUFFER POOL中的存放位置受以下隐含参数的影响: 隐含参数_db_percent_hot_default,默认值为50。表示SINGLE BLOCK I/O(如唯一键索引读)读取的数据块进入BUFFER CACHE之后,会将其放置在nK BUFFER POOL中LRU列的中间,即“热”端的尾部。MULTI BLOCK I/O(如对大表进行全表扫描)时,服务器进程会将大量的数据块读至BUFFER CACHE中,为了减轻对LRU列表中数据块(热块)的冲击,Oracle会将大表全表扫描的数据块存放至LRU列表的尾部,存放在LRU列表尾部的数据块可以尽快地被交换出BUFFER CACHE。 隐含参数_db_percent_hot_keep和_db_percent_hot_recycle,默认值为0。表示数据块进入到KEEP POOL和RECYCLE POOL时放在LRU列的尾端。 前面提到,Oracle为了提高性能会使用多个WORKING SET,并由CACHE BUFFERS LRU CHAIN LATCH保护。每一个CACHE BUFFERS LRU CHAIN LATCH对应一个WORKING SET,接下来将相对深入地探讨一下CACHE BUFFERS LRU CHAIN LATCH。 可以通过以下方法获取当前系统中CACHE BUFFERS LRU CHAIN LATCH的数量: 查询隐含参数_db_block_lru_latches。 通过查询V$LATCH_CHILDREN获得。如下所示:
SQL> select count(*) from v$latch_children
2 where name='cache buffers lru chain';
Oracle默认创建的CACHE BUFFERS LRU CHAIN LATCH的数量跟CPU的个数和DB_WRITER_PROCESSES参数有关。若DBWR数小于4,则创建4CPU_COUNT个CACHE BUFFERS LRU CHAIN LATCH,若DBWR数大于4,则创建DB_WRITER_PROCESSESCPU_COUNT个CACHE BUFFERS LRU CHAIN LATCH。从以上算法可以看出,CACHE BUFFERS LRU CHAIN LATCH的数量总是大于DBWR数量,即WORKING SET的数量总是大于DBWR的数量。不同的WORKING SET可以出现在不同类型的BUFFER POOL中,每个BUFFER POOL独立使用自己的CACHE BUFFERS LRU CHAIN LATCH 由于一个数据库实例可以配置8种不同类型的BUFFER POOL(DEFAULT、2KB、4KB、8KB、16KB、32KB、KEEP、RECYCLE BUFFER POOL),因此CACHE BUFFERS LRU CHAIN LATCH的数量至少为8个。可以通过以下查询获得各个BUFFER POOL中CACHE BUFFERS LAU CHAIN LATCH的使用情况: SQL> select d.blk_size,c.child#,p.bp_name,c.gets,c.sleeps 2 from x
k
c
b
w
d
s
d
,
v
kcbwds d, v
kcbwdsd,vlatch_children c, x$kcbwbpd p 3 where d.set_latch=c.addr 4 and d.set_id between p.bp_lo_sid and p.bp_hi_sid 5 order by c.child#;
BLK_SIZE CHILD# BP_NAME GETS SLEEPS
8192 1 KEEP 459 0
8192 2 KEEP 459 0
8192 3 RECYCLE 459 0
8192 4 RECYCLE 459 0
8192 5 DEFAULT 410618 2
8192 6 DEFAULT 402282 0
2048 7 DEFAULT 459 0
2048 8 DEFAULT 459 0
4096 9 DEFAULT 459 0
4096 10 DEFAULT 459 0
8192 11 DEFAULT 459 0
8192 12 DEFAULT 459 0
16384 13 DEFAULT 459 0
16384 14 DEFAULT 459 0
32768 15 DEFAULT 459 0
32768 16 DEFAULT 459 0
16 rows selected. 从上面的查询结果可以看出,目前系统存在16个CACHE BUFFERS LRU CHAIN LATCH,但只使用了2个。以下2种情况下必须要获得CACHE BUFFERS LRU CHAIN LATCH: 数据块读进BUFFER CACHE之前需要获得CACHE BUFFERS LRU CHAIN LATCH查找空闲缓冲区。 DBWR进程为了获得脏数据块列表,扫描LRU-W列之前需要获得CACHE BUFFERS LRU CHAIN LATCH。此外将空闲缓冲区移动至LRU辅助列,也需要获得CACHE BUFFERS LRU CHAIN LATCH。 当许多进程同时检索LRU列或者LRU-W列时,则容易出现LATCH: CACHE BUFFERS LRU CHAIN等待事件。一般来讲,CACHE BUFFERS LRU CHAIN LATCH争用最主要的原因是低效的SQL导致前台进程过多地请求空闲缓冲区引起的。与发生LATCH:CACHE BUFFERS CHAINS等待事件类似,不能简单地通过调整隐含参数_db_block_lru_latches来解决LATCH: CACHE BUFFERS LRU CHAIN等待事件。 在这里,读者需要仔细体会CACHE BUFFERS CHAINS LATCH和CACHE BUFFERS LRU CHAIN LATCH之间的区别: 多个会话并发访问相同的表或者索引时,则发生CACHE BUFFERS CHAINS LATCH争用的概率较高,因为相同表或索引的数据块多集中于几条相同的HASH CHAIN中。 多个会话并发访问不同的表或者索引时,则发生CACHE BUFFERS LRU CHAIN LATCH争用的概率较高,因为不同的数据块都存放在BUFFER CACHE中的概率较低,当发生物理读时需要更多地扫描LRU列和LRU-W列。
评论前必须登录!
注册