数据库版本:11.2.0.4.0

CBC latch出现的原因:   --只在逻辑读时产生

1.CBC latch保护不同的链表、不同BH   :同一LATCH下多个BUCKET被同时访问时,(一个LATCH对应多个BUCKET)

2.CBC latch保护同一链表下同一BH  :同一LATCH下同一BH被同时访问时

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、修改应用,减少全表扫描

BH上Buffer pin锁状态:

0 未加锁

1 共享锁,读BUFFER BLOCK  ---SELECT

2 独占锁,写BUFFER BLOCK   ---DML语句

Buffer pin锁争用引起:buffer busy waits等待事件 --热块

如何解决:buffer busy waits等待事件 --热块

1.增大PCTFREE

2.使用小数据块-2K-4K

3.使用HASH表分区

3.反向索引

同时出现CBC latch  buffer busy waits的情况是:

会话1已经获得Buffer pin锁,且已经释放CBC latch,正在持有Buffer pin锁

此时会话2获得与会话1同一个的CBC latch,并要获得与会话1 同一个块的Buffer pin锁,此时因会话1正持有Buffer pin锁,产生buffer busy waits等待事件

而会话1需要获得CBC latch,来释放持有的Buffer pin锁,此时会话2正在持有CBC latch,所以也将会产生CBC latch等待事件。

下面通过多会话同时访问产生热块的方式来模拟产生这两种等待:

1.查出表TEST相关信息--在数据量大的表实验更容易产生buffer busy waits

select rowid,


dbms_rowid.rowid_row_number(rowid) rowid_rownum,


dbms_rowid.rowid_relative_fno(rowid) file_id,


dbms_rowid.rowid_block_number(rowid) block_id,test.* from test;


ROWID              ROWID_ROWNUM    FILE_ID   BLOCK_ID OBJECT_NAME  STATUS


------------------ ------------ ---------- ---------- ------------ -------


AAAFSJAAEAAAACkAAA            0      

    4        164 10           15


AAAFSJAAEAAAACkAAB            1        

  4        164 10           15


可以看到,TEST表的两条记录在同一文件的同一个BLOCK中。


2.写一个循环:

循环执行查询语句一百万次:

--查询164数据块的第一行


declare


aa varchar2(100);


begin


for i in 1..1000000 loop


select object_name into aa from test where

rowid='AAAFSJAAEAAAACkAAA';


end loop;


end;


/



循环更新查询语句200次  

  --查询164数据块的第二行


declare


begin


for i in 1..200 loop


update test set status=15 where

rowid='AAAFSJAAEAAAACkAAB';


end loop;


commit;


end;


/


3.打开两个会话,查出会话SID。--这里会话SID分别是30 35.

在30号会话执行循环查询:


BYS@ bys3>select sid from v$mystat where rownum=1;


       SID


----------


        30


节约篇幅,执行循环的语句就不贴了。



在35号会话执行循环更新语句:


BYS@ bys3>select sid from v$mystat where rownum=1;


       SID


----------


        35


节约篇幅,执行循环的语句就不贴了。



4.再打开一个会话,使用语句查询35 30号会话的等待事件

23:03:20 SYS@ bys3>select sid ,event,total_waits,total_timeouts,time_waited_micro from v$session_event  


23:03:21   2  where sid in(30,35);



       SID EVENT                                    TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED_MICRO


---------- ---------------------------------------- ----------- -------------- -----------------


        30 buffer busy waits                                  1              0               968             --------这里30号会话是读操作,35号会话是写操作,也就是30号会话的读被写阻塞。

        30 latch: In memory undo latch                        1              0               960


        30 resmgr:cpu quantum                                 3              0             33589


        30 SQL*Net message to client                         15              0               637


        30 SQL*Net message from client                       14              0         206010788


        35 Disk file operations I/O                           3              0               312


       

35 latch: cache buffers chains                        2              0              1174


        35 db file sequential read                           64              0              9065


        35 direct path read                                 100              0             53191


        35 SQL*Net message to client                         25              0               259


        35 SQL*Net message from client                       24              0         625117659


        35 SQL*Net break/reset to client                      4              0              1046



12 rows selected.



Elapsed: 00:00:00.02


23:03:22 SYS@ bys3>select sid ,event,total_waits,total_timeouts,time_waited_micro from v$session_event


23:03:30   2  where sid in(30,35) and event like '%buffer%';



       SID EVENT                                    TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED_MICRO


---------- ---------------------------------------- ----------- -------------- -----------------


        30 buffer busy waits                                  1              0               968

        35 latch: cache buffers chains                        2              0              1174



Elapsed: 00:00:00.03


查看等待事件截图:

模拟产生CBC LATCH与buffer busy wait等待事件_数据块