oracle實驗記錄 (buffer_cache分析(1))

fufuh2o發表於2009-11-26

buffer cache中獲取block 過程
DML or select時候 oracle根據 SQL語句執行計劃,找到block,構造一個 叫buffer descriptor的block描述記憶體的結構(主要含block 實體地址 ,type,object id),這個block存在 session的 pga中,oracle應用buffer descriptor記錄的資訊 運用hash演算法,得到需要的block所在的hash bucket(確定block在哪條hash chain上),從 上面 掛的 第一個buffer header搜尋到最後一個buffer header,
hash chain上 搜尋邏輯 :
1.比較buffer header 上所記錄的block地址,不符合條件SKIP 此buffer header
2.skip status為cr的buffer header
3.如果buffer header狀態為 reading則等待,直到狀態改變後比較buffer header 記錄的block地址是否符合
4.若發現block地址符合的buffer header,查該buffer header是否位於正在使用的list上,如果是 則判斷已存在的lock mode,與要求的lock mode是否相容,如果相容則返回該buffer header中記錄的block地址,將當前process id放入buffer header 所處的正在使用的list上
5.如果lock mode不相容,用buffer header所指向的block中的內容構建一個xcurrent的block 和一個cr狀態的buffer header(指向新建立xcurrent狀態的 複製block)
6.搜尋完整個hash chain還未發現需要的buffer header,從disk讀取datafile,讀入到buffer cache中 相應的buffer header 掛在hash chain上


buffer cache指向block的狀態分6種
1.free =可以被重用的block
2.xcurrent=已EXCLUSIVE方式獲取的當前模式的block(insert,update,delete時產生),scurrent=可以與其他instance共享的當前模式block
3.cr=一致讀塊,永遠不會寫入disk
4.reading=正從disk讀取出來的塊
5.mreciver=正在進行介質恢復的block
6.ircovery=正在進行instance recovery的block


SQL> select distinct status from v$bh;

STATUS
-------
xcur
free
cr


buffer header
在buffer cache中,每一個block讀入 buffer cache時,都會在buffer cache中構造一個buffer header(buffer header與block一一對應)
1.存放該block在buffer cache中實際儲存地址
2.存放該block的型別(data,segment header,undo header,undo block等型別)
3.由於此buffer header 所在的hash chain,是通過在buffer header儲存指向前一個buffer header的指標和指向後一個buffer header的指標方式實現,所以還存指標
4.儲存lru,lruw,ckptq,fileq等佇列,一樣是通過記錄前後buffer header指標方式實現
5.當前該buffer header所對應的資料塊的狀態以及標記
6.該buffer header被訪問的次數(touch次數)
7.正在等待該buffer header的程式列表(waiter list)及正在使用此buffer header的(user list)

 


bucket 與cache buffers chains latch
oracle通過bucket管理buffer cache ,oracle用hash演算法將不同的buffer分配到bucket中,當需要定位需要的buffer是否在buffer cache中時,用同樣的hash 演算法 到相應的bucket上 搜尋對應的buffer header既可 bucket 中buffer header通過cache buffer chains連線(雙向連結串列)

查 buffer 中 預設 hash bucket數量既有多條hash chain
SQL> set linesize 132
SQL> column name format a30
SQL> column value format a25
SQL> select
  2    x.ksppinm  name,
  3    y.ksppstvl  value,
  4    y.ksppstdf  isdefault,
  5    decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE')  ismod,
  6    decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE')  isadj,x. KSPPDESC
  7  from
  8    sys.x$ksppi x,
  9    sys.x$ksppcv y
 10  where
 11    x.inst_id = userenv('Instance') and
 12    y.inst_id = userenv('Instance') and
 13    x.indx = y.indx and
 14    x.ksppinm like '%_&par%'
 15  order by
 16    translate(x.ksppinm, ' _', ' ')
 17  /
輸入 par 的值:  db_block_hash
原值   14:   x.ksppinm like '%_&par%'
新值   14:   x.ksppinm like '%_db_block_hash%'

NAME                           VALUE                     ISDEFAULT ISMOD      IS
ADJ
------------------------------ ------------------------- --------- ---------- --
---
KSPPDESC
--------------------------------------------------------------------------------
----------------------------------------------------
_db_block_hash_buckets         65536                     TRUE      FALSE      FA
LSE


oracle一直在優化hash buckets數目 因為 hash bucket 越多,存放的buffer header越分散(但bucket太多的話對空間,管理 都有壓力) 對於cache buffer chain latch爭用越少


檢視buffer header結構
SQL> create table t1 (a char(2000), b char(2000), c char(2000));

表已建立。

SQL> insert into t1 values ('a','a','a');

已建立 1 行。

SQL> insert into t1 values ('b','b','b');

已建立 1 行。

SQL> commit;

提交完成。

SQL> select header_file,header_block,owner from dba_segments where segment_name=
'T1';

HEADER_FILE HEADER_BLOCK OWNER
----------- ------------ ------------------------------
          4         1115 XH

SQL>  select file#,block# ,rowid from (select dbms_rowid.rowid_relative_fno(rowi
d) file#,dbms_rowid.rowid_block_number(rowid) block# ,rowid from T1);

     FILE#     BLOCK# ROWID
---------- ---------- ------------------
         4       1117 AAAMm+AAEAAAARdAAA
         4       1118 AAAMm+AAEAAAAReAAA
SQL> select object_id,data_object_id from user_objects where object_name='T1';

 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     51646          51646

SQL> select file#,block#,status,class# from v$bh where bjd=51646;

     FILE#     BLOCK# STATUS      CLASS#
---------- ---------- ------- ----------
         4       1118 xcur             1
         4       1113 xcur             8
         4       1116 xcur             1
         4       1119 xcur             1
         4       1114 xcur             9
         4       1117 xcur             1
         4       1120 xcur             1
         4       1115 xcur             4


SQL>

SQL> alter session set events 'immediate trace name buffers level 1';

會話已更改。

1.dump buffer header
2.1+block header
3.2+block內容
4.dump buffer header & hash chain
5.1+dump block header &hash chain (1+4)
6.2+dump block header &hash chain (2+4)
8.dump buffer header & hash chain+ user list+waiter list
9.1+dump block header & hash chain+ user list+waiter list
10.2+dump block內容+hash chain+ user list+waiter list

 

BH (15FEB49C) file#: 4 rdba: 0x0100045b (4/1115) class: 4 ba: 15CF6000
  set: 3 blksize: 8192 bsi: 0 set-flg: 2 pwbcnt: 239
  dbwrid: 0 obj: 51646 objn: 51646 tsn: 4 afn: 4
  hash: [2019a6a0,2019a6a0] lru: [15feb5a0,15feb440]
  ckptq: [15feb364,183eb414] fileq: [15feb36c,183eb41c] objq: [1eb25148,15feb494]
  st: XCURRENT md: NULL tch: 4
  flags: buffer_dirty gotten_in_current_mode redo_since_read
  LRBA: [0xb.22ea.0] HSCN: [0x0.d1044] HSUB: [1]

..................................

BH (15FEABAC) file#: 4 rdba: 0x01000460 (4/1120) class: 1 ba: 15CDC000
  set: 3 blksize: 8192 bsi: 0 set-flg: 2 pwbcnt: 239
  dbwrid: 0 obj: 51646 objn: 51646 tsn: 4 afn: 4
  hash: [201a8d38,201a8d38] lru: [15feacb0,163f3840]
  ckptq: [1a3f8304,15feac84] fileq: [2025c878,15feac8c] objq: [15fead04,1eb25148]
  st: XCURRENT md: NULL tch: 2
  flags: buffer_dirty gotten_in_current_mode redo_since_read
  LRBA: [0xb.2300.0] HSCN: [0x0.d1044] HSUB: [1]


...............................
在buffer cache中 一共可以找到 (select file#,block#,status from v$bh where bjd=51646;)對應的所有buffer header

分析:
  hash: [2019a6a0,2019a6a0]  就是指向前一個buffer header的指標 和 指向後一個buffer header的指標,x$bh中 NXT_HASH
 PRV_HASH,例中兩個值相等表示這個hash chain上只有一個buffer header

 

lru: [15feb5a0,15feb440] x$bh中 nxt_repl,prv_repl,lru上的下一個buffer和 上一個buffer,ckptq,fileq都是buffer修改後 使用的佇列
可以看出buffer header就是一個雙向連結串列組成

 

  class:表示buffer header對應block的型別,1=data block,2=sort block,3=save undo block,4=segment header,5=save undo header,6=free list,7=extent map,
8=1st level bmb;9=2nd level bmb;10=3rd level bmb;11=bitmap block;12=bitmap index block;13=unused;14=undo header;15=undo block。
對應v$bh中class#

rdba:buffer header對應的 塊地址
SQL> variable file# number;
SQL> variable blk# number;
SQL> execute :file#:=dbms_utility.data_block_address_file(to_number('1000460','x
xxxxxx'));

PL/SQL 過程已成功完成。


SQL> execute :blk#:=dbms_utility.data_block_address_block(to_number('1000460','x
xxxxxxx'));

PL/SQL 過程已成功完成。

SQL> print file#

     FILE#
----------
         4

SQL> print block#
SP2-0552: 未宣告繫結變數 "BLOCK#"。
SQL> print blk#

      BLK#
----------
      1120


另外可以 rdba: 0x01000460 ,100前3位代表file#,0460代表block#


SQL> select to_number('100','xxxx') file#,to_number('0460','xxxxxx') block# f
 dual;

     FILE#     BLOCK#
---------- ----------
       256       1120

 

整體buffer header內容 對應 x$bh,v$bh

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

相關文章