一. 相關說明
Oracle的資料放在表裡面,表的資料表段(segment)裡,segment 由extents 組成,extents 由Blocks組成。 每個block 可以存放多個row。
OracleSGA裡由一個DB buffer 的cache,該地區由default,keep 和 recycle pool組成。 預設情況下,block 會載入到defaultpool裡,Oracle 對資料區塊的所有操作都在這個pool裡進行,包括對資料的修改,修改之後,會有dbwr進行進行寫磁碟。 這個是一個比較複雜的過程,具體參考我的Blog:
二. 相關測試
2.1 建立一個死迴圈的預存程序
CREATE OR REPLACE PROCEDURE SYS.proc_test
AS
str varchar2(100);
i number;
BEGIN
i:=1;
while(true) loop
selectobject_name into str from t1 where object_name='RB_TEST';
if mod(i,1000) =0 then
DBMS_OUTPUT.put_line(i);
end if;
i :=i+1;
end loop;
END ;
/
--這個過程的作用就是迴圈的去訪問一個block
2.2 查看這個block的file_id 和 block_id
/* Formatted on 2011/7/4 19:45:56(QP5 v5.163.1008.3004) */
SELECT DBMS_ROWID.rowid_relative_fno(ROWID)REL_FNO,
DBMS_ROWID.rowid_block_number(ROWID)BLOCKNO,
DBMS_ROWID.rowid_row_number(ROWID) ROWNO
FROM t1
WHERE object_name = 'RB_TEST';
SYS@anqing2(rac2)> SELECTDBMS_ROWID.rowid_relative_fno (ROWID) REL_FNO,
2 DBMS_ROWID.rowid_block_number (ROWID) BLOCKNO,
3 DBMS_ROWID.rowid_row_number (ROWID) ROWNO
4 FROM t1
5 WHERE object_name = 'RB_TEST';
REL_FNO BLOCKNO ROWNO
---------- ---------- ----------
1 294838 54
2.3 開啟2個session,去調用這個過程,實現不斷訪問一個block
SYS@anqing2(rac2)> select sid from v$sesstat where rownum=1;
SID
----------
147
SYS@anqing1(rac1)> select sid fromv$sesstat where rownum=1;
SID
----------
141
SYS@anqing2(rac2)> exec proc_test
--持續進行,因為是個死迴圈---
SYS@anqing1(rac1)> exec proc_test
--持續進行,因為是個死迴圈---
2.4 查看等待事件
SYS@anqing1(rac1)> select event fromgv$session_wait where sid=147 and inst_id=2;
EVENT
----------------------------------------------------------------
latch: cache bufferschains
SYS@anqing1(rac1)> select event fromgv$session_wait where sid=141 and inst_id=1;
EVENT
----------------------------------------------------------------
latch: cache bufferschains
2.5 說明
本來測試資料區塊的串列訪問的,不過通過以上測試到類比了另一種情況: 熱塊導致的latch: cache buffers chains.
訪問頻率非常高的資料區塊被稱為熱快(Hot Block),當很多使用者一起去訪問某幾個資料區塊時,就會導致一些Latch爭用,最常見的latch爭用有:
(1)buffer busy waits
(2)cache buffer chain
這兩個Latch的爭用分別發生在訪問資料區塊的不同時刻。
當一個會話需要去訪問一個記憶體塊時,它首先要去一個像鏈表一樣的結構中去搜尋這個資料區塊是否在記憶體中,當會話訪問這個鏈表的時候需要獲得一個Latch,如果擷取失敗,將會產生Latch cache buffer chain 等待,導致這個等待的原因是訪問相同的資料區塊的會話太多或者這個列表太長(如果讀到記憶體中的資料太多,需要管理資料區塊的hash列表就會很長,這樣會話掃描列表的時間就會增加,持有chache buffer chain latch的時間就會變長,其他會話獲得這個Latch的機會就會降低,等待就會增加)。
當一個會話需要訪問一個資料區塊,而這個資料區塊正在被另一個使用者從磁碟讀取到記憶體中或者這個資料區塊正在被另一個會話修改時,當前的會話就需要等待,就會產生一個buffer busy waits等待。
產生這些Latch爭用的直接原因是太多的會話去訪問相同的資料區塊導致熱快問題,造成熱快的原因可能是資料庫設定導致或者重複執行的SQL 頻繁訪問一些相同的資料區塊導致。
這個圖是在我的buffer cache的那片blog 蕩過來的。 結合這個圖,我們來理解一下整個過程。資料區塊被載入到buffer cache,預設是載入到default pool。 那麼Oracle 是通過Hash bucket 和 Hash Chain 來管理。
將資料區塊分到不同的Hash bucket裡,每個Hash bucket 對應一個Hash Chain。 每個Hash Chain 裡儲存了資料區塊的位置和它前後的List 資訊。 而Hash Bucket 又是由Latches 進行控制,當我們想要找某個Hash bucket 上對應Hash Chain的資料區塊時,就要先拿到這個Latch。 如果很多session 去訪問某一個資料區塊,就產生了熱塊,當session A 拿到Latch 後,在Session A 釋放Latch 之前,其他Session
是拿不到這個Latch。因此,就產生了latch: cache buffers chains.的等待事件。
也因為這個Latch的原因,也讓並行的去訪問某一個資料區塊成為困難的事。
現在看一下,Session 拿到Latch 之後會做哪些操作。 這個聯絡x$bh 字典。
裡講到,該字典記錄了buffercache中每個block的情況。 當我們拿到latch 之後,Oracle 需要更新這個x$bh的資訊。如:
(1)state:
(2)tch: tch is the touch count. A hightouch count indicates that the buffer is used often. Therefore, it willprobably be at the head of the MRU list.
(3)tim: touch time.
(4)class:represents a value designated for the use of the block.
(5)flag :is a bit array.
x$bh字典表中的tch欄位表示的就是block的touch count,一般來說這個值越高那麼這個塊就越熱,我們稱這樣的塊就叫做熱點塊。
注意: user/all/dba_objects中的data_object_id關聯x$bh中的obj或者是v$bh中的objd。
SYS@anqing1(rac1)> selectfile#,block#,status,objd from v$bh where block#=294838;
--block 識別碼,之前查詢過
FILE# BLOCK# STATUS OBJD
---------- ---------- ------- ----------
1 294838 scur 56204
xcur:表示這個塊是排斥狀態正在被當前的instance獨佔。
scur: 表示這個塊正在被當前的instance共用
cr: 表示一致讀
free: 表示塊處在空閑狀態
read: 表示正在從磁碟上讀取塊
write: 表示塊正在被寫出
--查看tch 最多的塊
SYS@anqing2(rac2)> select * from (selectfile#,dbablk,tch from x$bh where obj=(select data_object_id from dba_objectswhere owner='SYS' and object_name='T1') order by TCH DESC) where rownum< 10;
FILE# DBABLK TCH
---------- ---------- ----------
1 74678 115
1 74911 115
6 144 115
6 377 115
1 294840 115
1 73602 115
1 75000 115
6 233 115
6 322 115
9 rows selected.