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 latch,hash bucket,hash 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 latch和hash bucket之间的关系变成了1:m。这样就很难计算某个hash chain具体的长度了。只能计算一个hash latch需要保护多少个数据块。而一个hash latch可能同时保护多个hash chain链表。上面的那个查询的结果变成了每个hash latch需要保护的数据块数。在你判断一个hash latch保护的数据块是否过量之前,需要先得到hash latch和hash bucket的比值。在下面的例子中,每个hash latch保护125个hash chain。如果你想要每个hash chain上不超过10个数据块,则每个hash latch保护的数据块不能超过1250个。通过隐含参数_db_block_hash_buckets可以增加hash bucket的数目,这样可以减少每个hash chain上的数据块数(因为hash bucket和hash chain之间是1:1的关系)。从oracle8i开始,一般不建议这么做。
Cache buffers lru chain latch
除了hash chain,缓冲头同样组成一个列表,这个列表指向其他的列表比如lru,lruw和ckpt-q。Lru和lruw列表并不是什么新东西,他们是数据缓冲区中最早的两个链表。Lru列表包含了不同状态的缓存块,而lruw就是俗称的“脏表”,只包含脏数据块。Lru和lruw列表是互斥的,他们合称一个工作集(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_children的addr列。
lru + lruw = a working set
一般来讲,当进程需要查找可用的缓存空间时,需要访问lru列表。后台进程DBWn则会将lruw列表中的干净块移到lru列表中,也会将lru中的脏块移到lruw列表中。在一个工作集中进行以上的任何操作都需要先获得cache buffers lru chain latch。
各个数据缓冲区中(包括不同块大小的缓冲区,keep池和recycle池),每个缓冲区至少需要有一个cache buffers lru chain latch,而一个DBWn进程可能需要多个latch。否则,一个工作集就可能变得很长。在oracle9i和oracle10g中,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 objects子latch。Oracle10g中,该latch也有了一个独立的等待事件:row cache objects。
从oracle7.0起,数据字典缓冲成为了共享池的一部分。而在7.0之前,每个数据字典对象都是由独立的dc_*初始化参数控制。Oracle7.0的这个改变也意味着,不能再直接的调整数据字典缓冲,而只能通过调整shared_pool_size来间接的调整。V$rowcache视图包含了每个数据字典对象的统计信息。你可以通过下面的查询发现最热的数据字典对象。
对数据字典缓冲区的调节手段是有限的。最好的办法是降低对前面的查询结果中一些热点数据字典对象的访问。举个例子,如果对某些sequence访问频繁,可以将考虑将这些sequnce缓存在内存中。包含多个基表连接或者基于视图的视图可能导致该latch争用。一般的解决办法是增加shared_pool_size的值。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/756652/viewspace-242309/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/756652/viewspace-242309/
本文探讨了Oracle数据库中几种常见锁(latch)的竞争问题及优化方案,包括cache buffers chains latch、cache buffers lru chain latch和rowcache objects latch等,并提供了详细的解决步骤。
2954

被折叠的 条评论
为什么被折叠?



