探究隱含引數_fairness_threshold

oliseh發表於2016-08-31

首先說明_fairness_threshold引數僅在RAC環境下才有意義,讓我對這個引數引起關注是在某一次查詢v$cr_block_server時,發現該檢視有一個名為FAIRNESS_DOWN_CONVERTS的欄位,官方文件裡將其解釋為:Number of times an instance receiving a request has down-converted an X lock on a block because it was not modifying the block

該引數相關效能指標在AWR的"Global CR Served Stats"章節裡也有出現:



根據我的理解,將FAIRNESS_DOWN_CONVERTS的含義翻譯為:RAC環境下的例項A對某個block在buffer cache里加上了Exclusive鎖,但例項A此時並沒有在修改該block,例項B請求從例項A的buffer cache裡讀訪問這個block,例項A接收到請求後先將這個block上的Exclusive鎖降級轉換後再傳輸給例項B,降級轉換一次,FAIRNESS_DOWN_CONVERTS值就+1。


要完全理解上述概念,我們至少需要搞清楚以下幾個問題:
1、例項B為何要從例項A的buffer cache裡訪問這個block?
2、例項A既然沒有在修改這個block,為何會對block持有Exclusive鎖?
3、鎖降級轉換目的在於?是否每一次跨例項傳輸block前都需要先進行鎖降級轉換?


逐個問題進行解答:
1、例項B為何要從例項A的buffer cache裡訪問這個block?
RAC裡所有例項的buffer cache通過高速專網進行互聯,Cache Fusion機制將各例項的buffer cache在邏輯上聚合成一個整體,當某個例項要訪問的block已被其它例項訪問過且仍保留在那個例項的bffer cache裡時,只要block的內容能夠滿足請求例項的訪問要求,該block就會通過高速專網從持有例項的buffer cache傳輸到請求例項的buffer cache裡,避免了請求例項從磁碟進行讀取。這之中有一個重要前提必須滿足,那就是保證持有例項block的內容是適合傳輸給請求例項的。換而言之,例項A要讀取的block在例項B的buffer cache裡,但若例項B Buffer cache裡的內容是N久之前的版本,這時例項A就只能從磁碟讀取了,異或者例項C的Buffer Cache擁有該block的較新版本,那麼例項A就會捨棄例項B和磁碟而從例項C讀取。如何為例項A選擇最為合適的資料來源,確保其能快速得到準確的查詢結果?一切盡在Global Resource Directory,簡稱GRD,只在RAC裡才有的GRD其實就是SGA裡的一塊記憶體區域存放內容包括了Global enqueue resource和Global cache resources,每個例項buffer cache裡的block就屬於global cache resource,每個block都有自己的master node,master node上的GRD裡準確記錄了這個block版本生成時的SCN、各節點持有的block鎖型別等資訊,可以通過gv$ges_resource檢視檢視block的master node是那個,比如對於scott.t0820_1表所在的block 6/255,其master_node為例項1:
select dbms_rowid.rowid_relative_fno(rowid) rfno,dbms_rowid.rowid_block_number(rowid) blkno from scott.t0820_1;
      RFNO      BLKNO
---------- ----------
         6        255


select to_char(6,'xxx'),to_char(255,'xxx') from dual;
TO_C TO_C
---- ----
   6   ff


select inst_id,resource_name,ON_GRANT_Q,ON_CONVERT_Q,master_node from gv$ges_resource where resource_name like '[0xff][0x6],[BL]%';
   INST_ID RESOURCE_NAME                  ON_GRANT_Q ON_CONVERT_Q MASTER_NODE
---------- ------------------------------ ---------- ------------ -----------
         1 [0xff][0x6],[BL][ext 0x0,0x0]           1            0           0     <---master_node=0表示例項1


假設一個四節點的RAC環境,block 6/255 存在於例項2的buffer cache裡,也存在於例項4的buffer cache裡,當例項3要查詢這個block時,先根據特定的hash演算法找到block的master node也就是例項1,例項1訪問自己的GRD後得知例項2 buffer cache裡的block剛修改過其SCN號比例項4裡的要大,而比例項3查詢發起時的SCN要小,所以例項1通知node 2將block傳輸給例項3,大致過程如下圖所示:




① S例項3要查詢block 6/255的內容,經過一定的hash演算法得出block 6/255的master node是例項1,於是例項3向例項1發起查詢block 6/255,此時的Query SCN=107
② 例項1查詢GRD後得知例項2上存在的block 6/255版本比例項4更新,更適合作為結果傳遞給例項1,所以例項1通知例項2要求其將該block傳輸給例項3
③ 例項2將自己buffer cache裡的block 6/255傳輸給例項3


RAC環境的各個例項都會存放一部分GRD資訊,具體位置是在shared pool裡,可以使用下面的語句瞭解這部分的記憶體佔用情況:
SELECT name,bytes FROM v$sgastat WHERE name LIKE 'ges resource%' OR name LIKE 'ges enqueues';
NAME                            BYTES
-------------------------- ----------
ges resource pools                744
ges resource hash seq tab       16384
ges enqueues                 11550936
ges resource                  5708880
ges resource hash table        720896


2、例項A既然沒有在修改這個block,為何會對block持有Exclusive鎖?
和單例項資料一樣,多例項的RAC環境下對block的訪問也需要獲得各種鎖,單例項與多例項鎖的對應關係如下:

單例項   多例項
NULL     KJUSERNL
RS       KJUSERCR
RX       KJUSERCW
S        KJUSERPR
SRX      KJUSERPW
X       KJUSEREX


其中KJUSERPR表示Protected read,KJUSEREX表示One process holds exclusive lock,我們暫只關注這兩種鎖。
通過一個小實驗來了解一下KJUSERPR和KJUSEREX在什麼情況下會出現


例項1:
create table scott.t0820_1 (id number);
insert into scott.t0820_1 values(1);
commit;
select * from scott.t0820_1;
        ID
----------
         1
         
select distinct dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) blkno from scott.t0820_1;
       FNO      BLKNO
---------- ----------
         6        255
         
alter system flush buffer_cache;
update scott.t0820_1 set id=2 where id=1;
commit;


set heading on 
select inst_id,file#,block#,status from gv$bh where file#=6 and block#=255 and status!='free';
   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        255 xcur
         1          6        255 cr


select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_8474.trc




alter system dump datafile 6 block 255;


在dump檔案susedb11_ora_8474.trc的尾端可以看到block 6/255在GRD裡的部分資訊:
GLOBAL CACHE ELEMENT DUMP (address: 0x8afaeaa8):
  id1: 0xff id2: 0x6 pkey: OBJ#15976 block: (6/255)
  lock: X rls: 0x0 acq: 0x0 latch: 4                     <---注意這裡lock: X代表了block上鎖型別為KJUSEREX
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xadf5b3b0,0xadf5b3b0]
  seq: 18 hist: 58 145:0 28 340 66 144:0 7 352 197 48 121 113 424
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02000001 state: XCURRENT tsn: 6 tsh: 2
      addr: 0xadf5b278 obj: 15976 cls: DATA bscn: 0x0.186dfc
      
在update語句commit後我們看到buffer cache裡出現了block 6/255的兩個版本,標示為cr的是update之前的before-image,標示為xcur的正是修改後的最新版本,xcur表示exclusive current,說明該block剛被更新過,buffer cache和磁碟上的內容可能不一樣(checkpoint尚未發生)也有可能已經一樣了(已發生checkpoint)。從上面的這段實驗內容可以看出儘管update所在事務已經提交但例項1還是持有著block 6/255上的exclusive鎖,雖然沒有釋放,但並不會影響其它例項對於block 6/255的訪問,後面會有對這個問題的解釋。


alter system flush buffer_cache;
select * from scott.t0820_1;


        ID
----------
         2


select inst_id,file#,block#,status from gv$bh where file#=6 and block#=255 and status!='free';


   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        255 scur


第二次flush buffer cache後緊接著作一次查詢,觀察到 block 6/255在buffer cache裡的型別變為了scur,scur表示shared current,說明該block在buffer cache和磁碟裡的內容一致。


再次dump後可以看到block上的鎖相應變成了Lock: S
alter system dump datafile 6 block 255;


GLOBAL CACHE ELEMENT DUMP (address: 0x8afaeaa8):
  id1: 0xff id2: 0x6 pkey: OBJ#15976 block: (6/255)
  lock: S rls: 0x0 acq: 0x0 latch: 4                      <---lock: S
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh01: kdstgr'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0 
  lcp: (nil) lnk: [NULL] lch: [0xa9f1c290,0xa9f1c290]
  seq: 28 hist: 66 144:0 7 352 197 48 121 113 424 180 58 145:0 28
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x00080000 state: SCURRENT tsn: 6 tsh: 1
      addr: 0xa9f1c158 obj: 15976 cls: DATA bscn: 0x0.186dfc


這個小實驗說明,最後修改過某個block的例項即便事務已經提交仍會在這個block上留下Exclusive鎖,當然這個Exclusive鎖是可以轉換成其它型別的,比如在checkpoint後會被scur取代


3、鎖降級轉換目的在於?是否每一次跨例項傳輸block前都需要先進行鎖降級轉換?
鎖降級轉換指的是buffer cache中的block狀態從xcur轉換為scur,考慮一下這個場景:
例項3為block A的master node,例項1會話修改了block A,此事例項1對block A持有Exclusive鎖,在v$bh裡的buffer型別是xcur,之後例項2會話把select訪問Block A的請求遞交給例項3,例項3根據GRD裡的資源資訊發現例項1 buffer cache裡的block A的xcur版本能滿足例項2的查詢要求,於是通知例項1將其buffer cache裡的block A傳送給例項2,按照一般的思路,例項1在向例項2傳輸前需要將Exclusive鎖轉換成Share模式的鎖(因為例項2是select訪問),然後再傳輸給例項2。但考慮到既然例項1修改了block A,其再次修改Block A的可能性還是很大的,如果將Exclusive鎖轉換成Share鎖,後續例項1再次修改block A時又需要從Share轉回Exclusive,在維護GRD的層面還是會產生不少開銷的。所以例項1在首次將block A傳送給例項2時並不會將其持有Exclusive鎖釋放或者轉換成其它型別,而是基於xcur型別的block A版本構造出一個型別為cr的buffer(內容與xcur型別的buffer完全一樣),將這個cr block傳送到例項2的buffer cache裡,例項2訪問cr block時無需加任何的鎖,但oracle為了加以區分還是上了一個NULL型別的鎖,準確的說它是一個placeholder型別的lock,在GRD裡這個鎖的名字是KJUSERNL。這種處理方式顯然能夠保留例項1對block持有的Exclusive鎖。但為此產生的代價是:從xcur構造出cr型別的block也是會產生一定開銷的,這其中包括
(1) build cr block的時間
(2) build cr block過程中產生的redo寫入online redolog的時間
一種較為極端的情況是若例項2後面對同一個block連續發起多次select操作,會引發例項1多次構造cr block的動作。於是Oracle在保留Exclusive鎖與構造cr block間作了一個折衷,提供了隱含引數_fairness_threshold,當select訪問次數達到引數指定值的時候,例項1會將block上的Exclusive鎖降級轉換成Shared鎖,對應的buffer也會從xcur轉換成scur型別,當例項2第_fairness_threshold+1次訪問相同block的時候例項1會把scur型別的block傳輸到例項2,之後例項2再次訪問相同block就只要從本地Buffer cache獲取。


我們還是通過具體實驗來體會一下_fairness_threshold引數的作用,其中需要用到的rec.sql指令碼內容如下:
***************
* rec.sql指令碼內容
***************
set heading off
select '----gv$cr_block_server----' from dual;
set heading on 
select inst_id,fairness_down_converts,fairness_clears,light_works from gv$cr_block_server order by inst_id;
set heading off
select '----gv$bh----' from dual;
set heading on 
select inst_id,file#,block#,status from gv$bh where file#=6 and block#=231 and status!='free';
set heading off
select '----x$bh----' from dual;
set heading on 
col object_name format a20
set linesize 80
select inst_id,dbarfil,dbablk,CR_SCN_BAS,DECODE(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi', 9,'memory',10,'mwrite',11,'donated', 12,'protected', 13,'securefile', 14,'siop',15,'recckpt', 16, 'flashfree', 17, 'flashcur', 18, 'flashna') state_name,tch from x$bh where dbarfil=6 and dbablk=231 and state!=0;


///////////////////////////////////
// 場景1:_fairness_threshold=2(預設值)
///////////////////////////////////
session說明:其中session 1 node X是真正參與測試的session,session 2 node X是專用來觀察相關檢視內容,獲取測試相關資訊的session


---session 1 node 1:修改其中一條記錄後commit;
alter system set optimizer_dynamic_sampling=0 scope=memory;


select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 A
         2 B


select distinct dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) blkno from scott.testfn_0730;
       FNO      BLKNO
---------- ----------
         6        231


update scott.testfn_0730 set col2='a' where id=1;
commit;


---session 2 node 1: 查詢_fairness_threshold引數值,記錄buffer cache裡block的狀態,DOWN_CONVERTS次數,light_works次數
col ksppinm format a30
col ksppstvl format a20
col ksppdesc format a60
col ksppstcmnt format a20
set linesize 200
select x.inst_id,ksppinm,ksppity,ksppstvl,ksppdesc from x$ksppi x, x$ksppcv y where (x.indx = y.indx) and ksppinm in ('_fairness_threshold');
   INST_ID KSPPINM                           KSPPITY KSPPSTVL             KSPPDESC
---------- ------------------------------ ---------- -------------------- ------------------------------------------------------------
         1 _fairness_threshold                     3 2                    number of times to CR serve before downgrading lock   


@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      4               0           0     <---node 1初始down_converts次數為4
         2                      4               0           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 xcur   <---session 1 node 1 update之後在buffer cache裡留下了xcur、cr兩個block,其中cr是block修改前的映像,xcur是當前最新的block映像
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         1          6        231          0 xcur
         1          6        231    1276027 cr             <---1276027是cr生成時的scn
         
---session 1 node 2:第一次訪問testfn_0730表
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數,light_works次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      4               0           0     <---down_converts次數未發生變化
         2                      4               0           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 xcur
         1          6        231 cr
         2          6        231 cr   <---node 2 buffer cache新增一型別為cr的block,正是由node 1以其xcur型block為基礎構造出來傳輸至node 2的




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         2          6        231    1276334 cr                <---node 2上cr block scn=1276334代表了其從xcur構造而來那一刻的系統scn號


---session 2 node 1: data block dump on node 1
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_16988.trc


alter system dump datafile 6 block 231;  <---dump block的內容,僅取出與GC有關的部分
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9b978):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: X rls: 0x0 acq: 0x0 latch: 6                             <--- node1:lock: X 表示block上有Exclusive鎖
  flags: 0x20 fair: 1 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xadf5d770,0xadf5d770]
  seq: 11 hist: 113 424 180 58 145:0 118 66 144:0 192 352 32
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02200000 state: XCURRENT tsn: 6 tsh: 2
      addr: 0xadf5d638 obj: 15930 cls: DATA bscn: 0x0.13787d
。。。省略部分內容


---session 2 node 2: data block dump on node 2
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb12/trace/susedb12_ora_18928.trc


alter system dump datafile 6 block 231;  <---dump block的內容
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9df78):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: C rls: 0x0 acq: 0x0 latch: 6    <--- node2:lock: C 其中的C代表Consistent,表示這個block是處於consistent read目的而生成的,其不能被服用,所以block上的鎖型別為KJUSERNL,KJUSERNL是一個placeholder型別的鎖
  flags: 0x21 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0x8af7e248,0xadffd5a8]
  seq: 6 hist: 329 144:6 14 7 352 32
。。。省略部分內容


---session 1 node 2:第二次訪問testfn_0730表
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      4               0           0
         2                      4               0           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 xcur
         1          6        231 cr
         2          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         2          6        231    1276334 cr
         
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      5               0           0          <---node 1的down convert次數從4增加到了5,發生了一次鎖降級轉換
         2                      4               0           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 scur              <---node 1的xcur降級成了scur
         1          6        231 cr
         2          6        231 cr
         2          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         2          6        231    1277433 cr            <---node 2上新增了一個SCN=1277433的cr,這個cr是在node 1上的xcur降級成scur之前構造出來的
         2          6        231    1276334 cr            <---這是第一次select後生成的cr


---session 2 node 1: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      6               0           0   <---node 1的down convert次數從5增加到了6,不清楚這次鎖降級轉換是由哪個block觸發的,但可以肯定與scott.testfn_0730表無關
         2                     22               1           0   <---node 2 down convert次數也從之前的4上升到22,也與scott.testfn_0730表無關,這裡我們不必關注




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 scur
         1          6        231 cr
         2          6        231 cr
         2          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         1          6        231          0 scur
         1          6        231    1276027 cr




---session 2 node 1: data block dump on node 1
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_19706.trc


alter system dump datafile 6 block 231;  <---dump block的內容,僅選取與GC有關的部分
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9b978):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: S rls: 0x0 acq: 0x0 latch: 6                           <---block dump結果容易看出node 1對block 6/231持有的鎖已從lock : X降級為lock : S
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xadf5d770,0xadf5d770]
  seq: 14 hist: 45 4 54 113 424 180 58 145:0 118 66 144:0 192 352 32
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02200000 state: SCURRENT tsn: 6 tsh: 2
      addr: 0xadf5d638 obj: 15930 cls: DATA bscn: 0x0.13787d
。。。省略部分內容


---session 2 node 2: data block dump on node 2
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb12/trace/susedb12_ora_20858.trc


alter system dump datafile 6 block 231;  <---dump block的內容
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9df78):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: C rls: 0x0 acq: 0x0 latch: 6                                  <---node 2還是保持為lock: C,即KJUSERNL鎖
  flags: 0x21 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0x8af954c8,0xadffd5a8]
  seq: 11 hist: 329 144:6 14 7 352 329 144:6 14 7 352 32
。。。省略部分內容  


---session 1 node 2:第三次訪問testfn_0730表,發現多出了型別為scur的buffer
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      7               0           0     <---比上一次增加了1
         2                     27               1           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 scur         <---node 2新生成出了一個scur,這個scur是從node 1傳輸過來的(node 1上的scur剛從xcur降級而來),scur表示該block在記憶體中的內容與磁碟上的內容一致
         2          6        231 cr
         2          6        231 cr
         1          6        231 scur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         2          6        231          0 scur
         2          6        231    1277433 cr
         2          6        231    1276334 cr


---session 2 node 1: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                      7               0           0
         2                     27               1           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 scur         
         2          6        231 cr
         2          6        231 cr
         1          6        231 scur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME
---------- ---------- ---------- ---------- ----------
         1          6        231          0 scur
         1          6        231    1276027 cr


---session 2 node 1: data block dump on node 1
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_21738.trc


alter system dump datafile 6 block 231;  <---dump block的內容,僅顯示與GC有關的部分
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9b978):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: S rls: 0x0 acq: 0x0 latch: 6                              <---node1對block的鎖維持lock: S
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xadf5d770,0xadf5d770]
  seq: 16 hist: 227 160 45 4 54 113 424 180 58 145:0 118 66 144:0 192
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02200000 lflg: 0x2 state: SCURRENT tsn: 6 tsh: 1
      addr: 0xadf5d638 obj: 15930 cls: DATA bscn: 0x0.13787d
。。。省略部分內容


---session 2 node 2: data block dump on node 2
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb12/trace/susedb12_ora_22849.trc


alter system dump datafile 6 block 231;  <---dump block的內容
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x89f9df78):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: S rls: 0x0 acq: 0x0 latch: 6 <---node 2上持有的鎖從lock: C變為了lock: S,因為node 2有了自己的scur block
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xabf5f310,0xabf5f310]
  seq: 16 hist: 227 144:0 213 7 352 329 144:6 14 7 352 329
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x08080000 state: SCURRENT tsn: 6 tsh: 1
      addr: 0xabf5f1d8 obj: 15930 cls: DATA bscn: 0x0.13787d
。。。省略部分內容          


---session 1 node 2:第四次訪問testfn_0730表,從第四次開始往後每次都是訪問scur這個buffer
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
SQL> @rec.sql


----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     37               2           1
         2                     40               1           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 scur
         1          6        231 cr
         2          6        231 scur
         2          6        231 cr
         2          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231          0 scur                3   <---scur的訪問次數一直在增加
         2          6        231    1277433 cr                  1
         2          6        231    1276334 cr                  1


---session 3 node 2:node 2上新開一個session訪問testfn_0730表,發現也都是訪問scur這個buffer,此時已不需要從遠端例項cache裡進行傳輸
select * from scott.testfn_0730;
         
SQL> @rec.sql


----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     44               2           1
         2                     40               1           0




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 scur              <---node 1、node 2的buffer數量沒有再增加
         1          6        231 cr
         2          6        231 scur
         2          6        231 cr
         2          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231          0 scur                4     <---tch數量的不斷上升表明node 2對block 6/231的訪問最後都落到了scur block上
         2          6        231    1277433 cr                  1
         2          6        231    1276334 cr                  1


小結一下:
_fairness_threshold=2時,當node 2第2次訪問node 1 buffer cache裡的block時,buffer cache裡該block的型別從xcur轉換成scur,v$cr_block_server.FAIRNESS_DOWN_CONVERTS計數器加1;node 1持有的鎖從Exclusive轉換為Share,node 2持有的鎖仍然是KJUSERNL;儘管如此,node 1仍然會構造出一個cr block傳送給node 2,我們能在node 2的buffer cache裡看到這個cr block;node 2第3次訪問block時,node 2 buffer cache裡才會新增一個從node 1傳輸而來的scur block,並且持有鎖的型別也從KJUSERNL變為了Share。如果block內容一直不被更改,從_fairness_threshold+2輪查詢開始node 2可在其本地的buffer cache裡直接訪問到該scur型別的block,不必從遠端的node 1節點獲得


下面看看_fairness_threshold=3的時候,是否遵循上述規律
///////////////////////////////
// 場景2:修改_fairness_threshold=3
///////////////////////////////
session說明:其中session 1 node X是真正參與測試的session,session 2 node X是專用來觀察相關檢視內容,獲取測試相關資訊的session


---session 1 node 1:修改其中一條記錄後commit;
alter system set optimizer_dynamic_sampling=0 scope=memory;


select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 A
         2 B


select distinct dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) blkno from scott.testfn_0730;
       FNO      BLKNO
---------- ----------
         6        231


update scott.testfn_0730 set col2='a' where id=1;
commit;


---session 2 node 1: 查詢_fairness_threshold引數值,記錄buffer cache裡block的狀態,DOWN_CONVERTS次數,light_works次數
col ksppinm format a30
col ksppstvl format a20
col ksppdesc format a60
col ksppstcmnt format a20
set linesize 200
select x.inst_id,ksppinm,ksppity,ksppstvl,ksppdesc from x$ksppi x, x$ksppcv y where (x.indx = y.indx) and ksppinm in ('_fairness_threshold');
   INST_ID KSPPINM                           KSPPITY KSPPSTVL             KSPPDESC
---------- ------------------------------ ---------- -------------------- ------------------------------------------------------------
         1 _fairness_threshold                     3 3                    number of times to CR serve before downgrading lock


@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     28               4           0
         2                     53               1           8




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         1          6        231 xcur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         1          6        231          0 xcur                2
         1          6        231    1800959 cr                  2
           
---session 1 node 2:第一次訪問testfn_0730表
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數,light_works次數
@rec.sql


----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     29               4           0
         2                     53               1           8




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 cr            <---node 2第一次訪問的是一個cr型別的block由node1構造後傳輸而來
         1          6        231 xcur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231    1800996 cr                  1


---session 1 node 2:第二次訪問testfn_0730表         
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     41               4           0
         2                     53               1           8




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 cr              <---node 2第二次訪問後在buffer cache裡有了第二個cr型別的block
         2          6        231 cr
         1          6        231 xcur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231    1801011 cr                  1         <---CR_SCN_BAS=1801011對應的cr block是第二次查詢所構造出的CR
         2          6        231    1800996 cr                  1 <---CR_SCN_BAS=1800996對應的cr block是第一次查詢所構造出的CR


---session 1 node 2:第三次訪問testfn_0730表
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     42               4           0     <---因為達到了_fairness_threshold所指定的閥值觸發了down convert動作,所以FAIRNESS_DOWN_CONVERTS較上次查詢的41增加了1
         2                     53               1           8




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 cr
         2          6        231 cr
         2          6        231 cr
         1          6        231 scur                  <---node 1 buffer cache中的xcur轉換成了scur
         1          6        231 cr




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231    1801037 cr                  1      <---第三次查詢構造出的cr
         2          6        231    1801011 cr                  1
         2          6        231    1800996 cr                  1
         
---session 2 node 1: data block dump on node 1
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_11782.trc


alter system dump datafile 6 block 231;  <---dump block的內容,僅取出與GC有關的部分
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x8cfd7568):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)                 
  lock: SG rls: 0x0 acq: 0x0 latch: 6                              <---lock:SG 表示node 1上已經降級成了Share鎖,G是global的意思
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.1ac5e4 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xabf051b0,0xabf051b0]
  seq: 13 hist: 170 1 4 54 58 145:0 28 340 239 144:0 7 352 32
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02000001 state: SCURRENT tsn: 6 tsh: 2
      addr: 0xabf05078 obj: 15930 cls: DATA bscn: 0x0.1b7b02 piscn: 0x0.1b7b4d
。。。省略部分內容


---session 2 node 2: data block dump on node 2
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb12/trace/susedb12_ora_10722.trc


alter system dump datafile 6 block 231;  <---dump block的內容
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x8aff9088):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: C rls: 0x0 acq: 0x0 latch: 6 <---lock:C 表示node 2持有的還是KJUSERNL型別的鎖
  flags: 0x21 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xb833b270,0x8afc13c8]
  seq: 22 hist: 329 144:6 14 7 144:5 192 352 329 144:6 14 7
。。。省略部分內容


---session 1 node 2:第四次訪問testfn_0730表
select * from scott.testfn_0730;
        ID COL2
---------- ----
         1 a
         2 B


---session 2 node 2: 記錄buffer cache裡block的狀態,DOWN_CONVERTS次數
@rec.sql
----gv$cr_block_server----




   INST_ID FAIRNESS_DOWN_CONVERTS FAIRNESS_CLEARS LIGHT_WORKS
---------- ---------------------- --------------- -----------
         1                     46               4           0
         2                     53               1           8




----gv$bh----




   INST_ID      FILE#     BLOCK# STATUS
---------- ---------- ---------- ----------
         2          6        231 scur                    <---第四輪查詢過後node 2上不再生成新的cr,取而代之的是node 1傳輸過來的scur
         2          6        231 cr
         2          6        231 cr
         2          6        231 cr
         1          6        231 scur
         1          6        231 cr


6 rows selected.




----x$bh----




   INST_ID    DBARFIL     DBABLK CR_SCN_BAS STATE_NAME        TCH
---------- ---------- ---------- ---------- ---------- ----------
         2          6        231          0 scur                1
         2          6        231    1801037 cr                  1
         2          6        231    1801011 cr                  1
         2          6        231    1800996 cr                  1


---session 2 node 1: data block dump on node 1
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb11/trace/susedb11_ora_10588.trc


alter system dump datafile 6 block 231;  <---dump block的內容,僅選取與GC有關的部分
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x8cfd7568):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: SG rls: 0x0 acq: 0x0 latch: 6 <---lock:SG node 1上仍然維持Share鎖
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.1ac5e4 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xabf051b0,0xabf051b0]
  seq: 20 hist: 225 212 424 72 257 59 227 170 1 4 54 58 145:0 28 340
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x02200000 state: SCURRENT tsn: 6 tsh: 2
      addr: 0xabf05078 obj: 15930 cls: DATA bscn: 0x0.1b7b02
。。。省略部分內容


---session 2 node 2: data block dump on node 2
select value from v$diag_info where name='Default Trace File';


VALUE
--------------------------------------------------------------------------------
/oracle/app/oracle/diag/rdbms/susedb1/susedb12/trace/susedb12_ora_11315.trc


alter system dump datafile 6 block 231;  <---dump block的內容
。。。省略部分內容
GLOBAL CACHE ELEMENT DUMP (address: 0x8aff9088):
  id1: 0xe7 id2: 0x6 pkey: OBJ#15930 block: (6/231)
  lock: S rls: 0x0 acq: 0x0 latch: 6                            <---lock:SG node 2從KJUSERNL類的鎖轉換成Share鎖
  flags: 0x20 fair: 0 recovery: 0 fpin: 'kdswh11: kdst_fetch'
  bscn: 0x0.0 bctx: (nil) write: 0 scan: 0x0
  lcp: (nil) lnk: [NULL] lch: [0xabeefc70,0xabeefc70]
  seq: 29 hist: 227 144:0 213 7 144:5 192 352 329 144:6 14 7
  LIST OF BUFFERS LINKED TO THIS GLOBAL CACHE ELEMENT:
    flg: 0x08080000 state: SCURRENT tsn: 6 tsh: 1
      addr: 0xabeefb38 obj: 15930 cls: DATA bscn: 0x0.1b7b02
。。。省略部分內容  


小結一下:
_fairness_threshold=3時,當node 2第3次訪問node 1 buffer cache裡的block時,node 1 buffer cache裡該block的型別從xcur轉換成scur,v$cr_block_server.FAIRNESS_DOWN_CONVERTS計數器加1;node 1持有的鎖從Exclusive轉換為Share,node 2持有的鎖仍然是KJUSERNL;此時,node 1仍然會構造出一個cr block傳送給node 2,我們能在node 2的buffer cache裡看到這個cr block;node 2第4次訪問block時,node 2 buffer cache裡才會新增一個從node 1傳輸而來的scur block,並且持有鎖的型別也從KJUSERNL變為了Share。如果block內容一直不被更改,從_fairness_threshold+2輪查詢開始node 2可在其本地的buffer cache裡直接訪問到該scur型別的block,不必從遠端的node 1節點獲得


總結:
_fairness_threshold的可以看出oracle研發過程中的精雕細琢,為了在鎖轉換產生的開銷與cr block構造產生的開銷之間找到平衡,提供_fairness_threshold引數的同時給了使用者一個靈活調節的手段,細節決定成敗,Oracle RAC無愧為業界優秀的資料庫叢集軟體

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

相關文章