1.CBC latch产生的原理:
一次逻辑读时CBC latch锁及Buffer pin锁的获取和释放过程如下:
1.加Latch X
2.进入hash chain,在相应的BH上加Buffer pin S (0-->1)
3.释放Latch X
4.进行逻辑读--也就是通过BH中的buffer adderss找到数据块在内存中真实位置 ---假如读了1MS
5.加Latch X
6.释放Buffer pin S (1-->0) 0:没锁 1:共享锁 2:独占锁
7.释放Latch X
物理读时需要将数据块的buffer header挂载到hash chain上,也需要获取CBC LATCH,buffer header中有hash chain的信息,BH挂载到hash chain上,应该在BH内存结构中会有信息更改,BH的修改也就需要有Buffer pin了,锁的获取和释放应该和逻辑读时差不多,不过是在Buffer pin S 上要加2号独占锁。当然这一点是我大胆推测的哈哈。
CBC latch上一般都用的独占锁,使用共享锁的情况是:9I后在索引的根、枝叶读时使用共享CBC LATCH,无BUFFER PIN方式访问上
BH上Buffer pin锁状态:
0 未加锁
1 共享锁,读BUFFER BLOCK ---SELECT
2 独占锁,写BUFFER BLOCK ---DML语句
2.从CBC latch产生的原理可以发现,出现CBC LATCH争用会有以下情况:
1.CBC latch保护不同的链表、不同BH :同一CBC LATCH下多个hash chain上的多个BH被同时访问时,
2.CBC latch保护同一链表下同一BH :同一hash chain上同一BH被同时访问时
3.物理读将数据块挂载到hash chain上时,多个物理块HASH冲突都挂载到同一个hash chain或者要挂载的hash chain上的BH在被逻辑读
这里的被访问,可能发生在逻辑读或者物理读,即:使用到CBC latch的场景是:
服务器进程需要扫描hash chain上数据块--逻辑读
服务器进程需要将数据块挂载到hash chain上--物理读
关于hash chain与hash bucket,详见本系列第一篇:
点击打开链接
3.关于CBC LATCH争用的模拟实验,有两种思路:
一是热链--这个不太好模拟,我也没做成功。
二是热块-这个好模拟,同时还会有buffer busy waits,具体实验见:
点击打开链接
4.latch: cache buffers chains 解决思路:
1、热链:调整_db_block_hash_latches加大latch数量,作用是减少同一LATCH下多个桶被同时访问的情况。即多个表的相应块在BUFFER CACHE中对应不同BH,不同BH又对应在不同HASH BUCKETS,但是这多个HASH BUCKETS是属于同一个LATCH。。
alter system set "_db_block_hash_latches"=10240 scope=spfile;
2、热块:调整BUFFER _CACHE,参数:db_cache_size,big integer 100M
热块是:同一表在BUFFER CACHE中的块(一个块对应一个BH,BH对应一个HASH BUCKET)被多个会话同时读,--全表扫描时容易出现。可以使用多个会话同时读取同一表的同一行的方式来模拟产生CBC latch,查询时使用ROWID做条件,查询速度快,更容易引起CBC latch。
3、修改应用,减少全表扫描,也就是优化SQL语句了
例如:CBC Latch的产生次数的查询:
SYS@ bys3>col name for a20
SYS@ bys3>select NAME,GETS ,MISSES ,SLEEPS ,IMMEDIATE_GETS, IMMEDIATE_MISSES from v$latch where name like '%cache buffers chains%';
NAME GETS MISSES SLEEPS IMMEDIATE_GETS IMMEDIATE_MISSES
-------------------- ---------- ---------- ---------- -------------- ----------------
cache buffers chains 2006932 0 0 78095 0