latch free(cache buffers chain)

oracle_ace發表於2008-03-07
         Oracle在buffer cache記憶體管理中利用hash table來提高程式檢索資料的速度,一般來說oracle利用hash演算法將buffer cache分割成不同的hash bucket,每hash bucket都會有一個hash鏈(cache buffers chains)來管理buffer cache中的每一個buffer,那麼這些buffer的header就是存放在這個cache buffers chains上面的,因此程式根據pid的hash演算法,來訪問某一個hash bucket中的buffer header時,首先要獲得每一個hash bucket中cache buffers chains的一個latch,也就是我們所謂的閂。latch其實就是一種非常低階的序列化裝置,和鎖的資料結構有著截然不同的特點,只所以說他是低階的,就是因為相比鎖來講他的獲得和釋放都非常的快。同時latch的存在會使的我們的共享裝置在程式併發訪問的情況下對其進行資料結構的保護。
下面來做個實驗就是,讓一個block很熱,從而觀察cache buffers chains上面latch的競爭。

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
PL/SQL Release 9.2.0.8.0 - Production
CORE    9.2.0.8.0       Production
TNS for 32-bit Windows: Version 9.2.0.8.0 - Production
NLSRTL Version 9.2.0.8.0 - Production

SQL> select file_name from dba_data_files;

FILE_NAME
----------------------------------------------------------------------

D:\ORACLE\ORA92\ICMNLSDB\SYSTEM01.DBF
D:\ORACLE\ORA92\ICMNLSDB\UNDOTBS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\INDX01.DBF
D:\ORACLE\ORA92\ICMNLSDB\TOOLS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\USERS01.DBF

SQL> create tablespace assm
  2  datafile 'D:\ORACLE\ORA92\ICMNLSDB\assm.dbf' size 10M
  3  extent management local uniform. size 1M
  4  segment space management auto;

表空間已建立。

SQL> create table t
  2  (id number,
  3   name char(10)) tablespace assm;

表已建立。

SQL> insert into t values (1,'A');

已建立 1 行。

SQL> commit;

提交完成。

SQL> select id,rowid from t;

        ID ROWID
---------- ------------------
         1 AAAGP5AAGAAAAAXAAA

這裡我們只插入一行的資料,然後頻繁的針對這個block進行併發訪問,導致這個block header所在的cache buffers chains上的latch產生競爭。

建立測試指令碼
SQL> create or replace procedure latch_test
  2  as
  3  cursor my_cursor is select id from t where rowid='AAAGP5AAGAAAAAXAAA';
  4  t_result number(5);
  5  begin
  6  for i in 1..700000 loop
  7  open my_cursor;
  8  fetch my_cursor into t_result;
  9  close my_cursor;
 10  end loop;
 11  end;
 12  /

過程已建立。

在3個session上面同時執行測試指令碼,並進行監控:

執行指令碼之前......

SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
  2  from v$session_event
  3  where sid in (7,8,9) and event like '%latch%';

未選定行

SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
  2  from v$latch where name='cache buffers chains';

    MISSES       GETS     SLEEPS  SPIN_GETS     SLEEP1     SLEEP2     SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
    SLEEP4
----------
         0       8241          0          0          0          0          0
         0

開始在3個不同的session同時執行指令碼......

繼續觀察

SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
  2  from v$session_event
  3  where sid in (8,9,10) and event like '%latch%';

       SID EVENT
---------- ----------------------------------------------------------------
TIME_WAITED TIME_WAITED_MICRO TOTAL_TIMEOUTS TOTAL_WAITS
----------- ----------------- -------------- -----------
         8 latch free
         84            838857             15          24

         9 latch free
         80            803321             15          28

        10 latch free
        101           1011249             17          30

這裡出現了三個等待事件,正好是我們在執行指令碼時的三個session 8,9,10。

SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
  2  from v$latch where name='cache buffers chains';

    MISSES       GETS     SLEEPS  SPIN_GETS     SLEEP1     SLEEP2     SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
    SLEEP4
----------
        78    4209205         81          0         75          3          0
         0

因為三個session都在併發的去爭奪同一個cache buffer chains上的latch,從而會導致latch的競爭。

如果是單讀一個session對block進行訪問,我們可以只看到這個latch被gets.而競爭消失。
SQL> /

    MISSES       GETS     SLEEPS  SPIN_GETS     SLEEP1     SLEEP2     SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
    SLEEP4
----------
        78    5609271         81          0         75          3          0

參考這個
http://space.itpub.net/13095417/viewspace-172809

記錄一下sleeps和sleep 1,2,3,4的關係:
sleeps=sleep1*1 + sleep2 * 2 + sleep3 * 3 + ........

v$latch的欄位描述
gets       以願意等待模式請求閂,並獲得的次數.
misses     以願意等待模式請求閂,自旋或睡眠後獲得的次數.
sleeps     以願意等待模式請求閂,睡眠的次數.
spin_gets  第一次自旋即成功獲得閂的次數.
sleep1     睡眠一次後獲得閂的次數.
sleep2     睡眠兩次後獲得閂的次數.
sleep3     睡眠三次後獲得閂的次數.
sleep4     睡眠四次以上獲得閂的次數.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12361284/viewspace-201610/,如需轉載,請註明出處,否則將追究法律責任。

相關文章