数据库版本: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
查看等待事件截图: