ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Latch free等待事件四

Latch free等待事件四

原创 Linux操作系统 作者:chinagjj2008 时间:2009-04-14 09:02:05 0 删除 编辑

n 尽量减每个块中的记录数。首先需要dump一些数据块来分析现在每个块中的记录数。Dump出来的跟踪文件中,nrow就是块中的记录总数。然后exp表,再truncate表,在表中插入你想要在每个块中保存的条数的记录,然后使用alter table table_name minimize records_per_block,再truncate表,最后imp回数据即可。

n 可以考虑减少块的大小。从oracle9i开始,数据库可以支持不同的块大小。例如当前块大小为16k,你可以将表及其索引移动块大小为8k的表空间中。这也会对全表扫描造成负面影响。并且,多个块大小也会使得管理更复杂。

另外,从oracle9iR2开始,也可以通过增加隐含参数_spin_count的值来解决热点块导致的cache buffers chains latch争用。最后,也可以通过隐含参数_db_block_hash_buckets来增加hash bucket的数量,从oracle8i开始,一般不建议采用这种办法,如果实在要用,请保证_db_block_hash_buckets的值为一个质数,否则,oracle也会自动采用大于你提供的值的最小的质数值。

Cache buffers chains latch争用原因三 ―― 过长的hash chain

多个数据块可能分配到同一个hash bucket上。这些块组成一个链表(hash chain)。在一个大型系统中,一个hash bucket中可能有上百个数据块。从一个hash chain链表中搜索某个块,需要获得cache buffers chains latch,串行的进行。如果链表太长,使得latch持有时间相应增加,可能导致其他进程请求cache buffers chains latch失败。

oracle8.0之前,由于hash latchhash buckethash chain之间是1:1:1的关系,很容易计算一个hash chain的长度,等于一个latch需要保护的数据块数。通过下面的查询可以知道一个hash chain上的数据块数。一般而言,一个hash chain链表上超过10个数据块就认为太长了。

Select hladdr, count(*)
from x$bh
group by hladdr
order by 2;

oracle8i起,hash latchhash bucket之间的关系变成了1:m。这样就很难计算某个hash chain具体的长度了。只能计算一个hash latch需要保护多少个数据块。而一个hash latch可能同时保护多个hash chain链表。上面的那个查询的结果变成了每个hash latch需要保护的数据块数。在你判断一个hash latch保护的数据块是否过量之前,需要先得到hash latchhash bucket的比值。在下面的例子中,每个hash latch保护125hash chain。如果你想要每个hash chain上不超过10个数据块,则每个hash latch保护的数据块不能超过1250个。通过隐含参数_db_block_hash_buckets可以增加hash bucket的数目,这样可以减少每个hash chain上的数据块数(因为hash buckethash chain之间是1:1的关系)。从oracle8i开始,一般不建议这么做。

_db_block_hash_buckets = 128021
_db_block_hash_latches = 1024
ratio = 128021 / 1024 = 125

Cache buffers lru chain latch

除了hash chain,缓冲头同样组成一个列表,这个列表指向其他的列表比如lrulruwckpt-qLrulruw列表并不是什么新东西,他们是数据缓冲区中最早的两个链表。Lru列表包含了不同状态的缓存块,而lruw就是俗称的“脏表”,只包含脏数据块。Lrulruw列表是互斥的,他们合称一个工作集(a working set)。每个工作集由一个cache buffers lru chain latch保护。换句话说,数据缓冲区中工作集的个数是由cache buffers lru chain latch的个数决定的。通过内部视图x$kcbwds (kernel cache buffer working sets descriptors)可以知道工作集的个数。我们注意到x$kcbwds set_latc的值就是v$latch_childrenaddr列。

lru + lruw = a working set

Select set_id, set_latch 
from x$kcbwds
order by set_id;

set_id set_latc
  
---------- --------
1 247e299c
2 247e2e68
3 247e3334
4 247e3800
5 247e3ccc
6 247e4198
7 247e4664
8 247e4b30

select addr
from v$latch_children
where name = ’cache buffers lru chain’
order by addr;

addr
--------
247e299c
247e2e68
247e3334
247e3800
247e3ccc
247e4198
247e4664
247e4b30

一般来讲,当进程需要查找可用的缓存空间时,需要访问lru列表。后台进程DBWn则会将lruw列表中的干净块移到lru列表中,也会将lru中的脏块移到lruw列表中。在一个工作集中进行以上的任何操作都需要先获得cache buffers lru chain latch

各个数据缓冲区中(包括不同块大小的缓冲区,keep池和recycle池),每个缓冲区至少需要有一个cache buffers lru chain latch,而一个DBWn进程可能需要多个latch。否则,一个工作集就可能变得很长。在oracle9ioracle10g中,cache buffers lru chain latch的个数默认是cpu个数的4倍,如果,db_writer_processes大于4,则等于cpu的个数乘以db_writer_processes。可以通过隐含参数_db_block_lru_latches来调节cache buffers lru chain latch的个数。

Cache buffers laru cahin latch的争用,主要表现为由于低效的sql语句导致数据缓冲区过度活跃。全表扫描和对某些选择性较差的大索引的反复扫描是造成cache buffers laru cahin latch争用的主要原因。解决办法是,查找latch free等待事件中关于cache buffers lru chain latch相关的sql语句(在oracle10g中,已经变成一个独立的cache buffers lru chain等待事件),优化这些sql,降低其物理读和逻辑读。

Row cache objects latch

Row cache objects latch用来保护数据字典缓冲区(row cache的名字主要是因为其中的信息是按行存储的,而不是按块存储)。进程在装载、引用或者清除数据字典缓冲区中的对象时必须获得该latch。在oracle8i之前,这是一个独立latch。从oracle9i起,由于引入了多个子共享池的新特性,存在多个row cache objectslatchOracle10g中,该latch也有了一个独立的等待事件:row cache objects

oracle7.0起,数据字典缓冲成为了共享池的一部分。而在7.0之前,每个数据字典对象都是由独立的dc_*初始化参数控制。Oracle7.0的这个改变也意味着,不能再直接的调整数据字典缓冲,而只能通过调整shared_pool_size来间接的调整。V$rowcache视图包含了每个数据字典对象的统计信息。你可以通过下面的查询发现最热的数据字典对象。

Select cache#, type, parameter, gets, getmisses, modifications mod 
from v$rowcache
where gets > 0
order by gets;

cache# type parameter gets getmisses mod
------ ----------- ------------------ ---------- ---------- ------
7 subordinate dc_user_grants 1615488 75 0
2 parent dc_sequences 2119254 189754 100
15 parent dc_database_links 2268663 2 0
10 parent dc_usernames 7702353 46 0
8 parent dc_objects 11280602 12719 400
7 parent dc_users 81128420 78 0
16 parent dc_histogram_defs 182648396 51537 0
11 parent dc_object_ids 250841842 3939 75

对数据字典缓冲区的调节手段是有限的。最好的办法是降低对前面的查询结果中一些热点数据字典对象的访问。举个例子,如果对某些sequence访问频繁,可以将考虑将这些sequnce缓存在内存中。包含多个基表连接或者基于视图的视图可能导致该latch争用。一般的解决办法是增加shared_pool_size的值。

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

请登录后发表评论 登录
全部评论

注册时间:2008-01-14

  • 博文量
    32
  • 访问量
    59932