探究隐含参数_fairness_threshold


首先说明_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/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/53956/viewspace-2124241/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值