模擬產生CBC LATCH與buffer busy wait等待事件

還不算暈發表於2013-12-10
  資料庫版本: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
檢視等待事件截圖:

相關文章