• RAC object remastering ( Dynamic remastering )


    RAC环境中,每个数据块都被一个instance所管控(mastered),管控数据块的instance被称作主实例(master instance)。管控数据块就是说主实例(master instance)会一直跟踪数据块的状态,直到下一次重新配置事件发生,比如实例重启或其它原因。
     
    Hash to the master
    数据库根据数据块范围来管控数据块。比如,第10号数据文件的block 1到block128范围内的数据块被instance 1所管控,block 129到block 256范围内的数据块被instance 2所管控。10g和11g中会有所不同,但中心思想不变。即将数据块按照块范围在不同实例之间进行管控,使得global cache grants可以在不同实例之间平衡分布。
    10g以后,块范围是128。(技术支持推荐取消db_file_multiblock_read_count初始化参数的设置这样将会自动调整到128,估计这意味着通过较少的GC消息就可以进行完整的多块读)
     
    Michael Möller指出,这种hash算法有进一步的优化:最初的hash算法根据数据块地址(DBA)来计算master node,生成“虚拟master”(virtual master),然后在通过一个查询表(长度是最大允许的节点数,128?)再转化为真实(在线且打开的)属主。这意味着当有一个节点离线或上线后,RAC不需要为所有数据块再次计算哈希值,而只需要分发新的Hash-to-node表。(在节点发生变化时也同样需要重新分发)
     
    以下SQL有助于显示数据块的属主(master)和拥有者(owner)。这个SQL结合了x$kjbl和x$le表来获得资源的名称。如果对于Oracle锁机制比较熟悉,可能认识这些缓存融合(cache fusion)锁(以前的PCM锁)的结构。这里锁类型是BL,id1是block#,id2是file_id。列kjblname2显示的是锁资源的十进制数字格式。
     
    请注意下面的输出:
    1.数据块范围:File 1, block 6360-6376为node 3所管控也属于node 3
    2.数据块范围:File 1,一直到10709数据块为实例0所管控,属于实例3
    3.从10770开始的下一个数据块范围为实例2所管控,属于实例3
     
    另外,这些输出是从一个还没有remastering操作的数据库中获得的。
     
    kjblname2列逗号前第一部分是数据块,第二部分file_id*65536是BL locks
    select kj.*, le.le_Addr
      from (select kjblname,
                   kjblname2,
                   kjblowner,
                   kjblmaster,
                   kjbllockp,
                   substr(kjblname2,
                          instr(kjblname2, ',') + 1,
                          instr(kjblname2, ',', 1, 2) -
                          instr(kjblname2, ',', 1, 1) - 1) / 65536 fl,
                   substr(kjblname2, 1, instr(kjblname2, ',') - 1) blk
              from x$kjbl) kj,
           x$le le
     where le.le_kjbl = kj.kjbllockp
     order by le.le_addr
    /
    
    KJBLNAME               KJBLNAME2       KJBLOWNER KJBLMASTER   FL    BLK LE_ADDR
    ---------------------- --------------- ---------- ----------- --- ----- ----------------
    [0x18d8][0x10000],[BL] 6360,65536,BL           3          3     1  6360 000000038DF9AB08
    ...
    [0x18e7][0x10000],[BL] 6375,65536,BL           3          3     1  6375 000000038DFBF818 => case #2
    [0x18e8][0x10000],[BL] 6376,65536,BL           3          3     1  6376 000000038DFD3BA0
    ...
    [0x29d1][0x10000],[BL] 10705,65536,BL          3          0     1 10705 00000005D6FE9230
    ...
    [0x29d5][0x10000],[BL] 10709,65536,BL          3          0     1 10709 000000038EFBB990
    [0x2a12][0x10000],[BL] 10770,65536,BL          3          2     1 10770 000000075FFE3C18
    ...
    [0x2a18][0x10000],[BL] 10776,65536,BL          2          2     1 10776 000000038EFA8488 => case #1
    [0x2a19][0x10000],[BL] 10777,65536,BL          3          2     1 10777 000000038EFB7F90
    [0x2a1a][0x10000],[BL] 10778,65536,BL          1          2     1 10778 000000038EFCC318
    

    让我们假设在instance 3上发生以下3种select操作:

    1.一个会话尝试读取数据文件1中的块10776,但是这个数据块被instance2管控和拥有(即该数据块在instance 2的buffer cache中)。所以,instance 3将给instance 2发送一个PR(Protected Read)模式的BL锁要求读取该块。忽略其他复杂的细节,instance 2会给instance 3授予PR模式的锁,并将数据块传送给instance 3。显然,这将会涉及多个GC消息,以及锁授予和块传递。统计值’gc remote grants’也会增加。

    2.假设此会话尝试读取数据块file 1, block 6375。此块为instance 3管控,同时被instance 3拥有,这时就不会有额外的GCS/GES过程了,会话直接pin住buffer然后继续工作。

    3.考虑第三种情况,会话尝试读取数据块file 1 block 6374。此块不在任何实例的buffer cache中,但是实例3是这个块的属主,所以只需要消耗少量GC消息和等待而获得本节点的affinity locks,然后将数据块从磁盘读到缓存中来。   在上面的2和3中,请求者实例同时也是数据块或者块范围的属主节点。在这种情况下,统计值'gc local grants'增加,这些块上获得的本节点的affinity locks代价较低,这样避免了大量的全局缓存消息。

    此外,如果数据块即将从缓冲池中移走或者即将被修改,就会导致在主实例和其它实例之间的额外消息开销,因为所有权信息需要再被送回块的属主处。

    Object Remastering

    在10g/11g RAC中有很多新功能。其中一个就是object remastering。这个特性在10gR1中引入,10gR2中得到改善,11g中的得到进一步增强。其实在9i中也有相应的参数,不过实际上并不能正常工作。有了object remastering特性后,如果一个object频繁被一个instance访问,那么那个instance会变成该object的master,从而减少gc remote grants,提升性能。

    理想情况下,即使应用程序没有完善的分区策略, remastering被某个实例频繁读取的对象也会使得获取本地实例亲和锁(affinity locks)低价更低,从而使RAC开销下降。

    现实中还存在以下一些问题:

    1.重启后,instance无法记得之前的属主关系。每次重启后都要重新"学习"

    2.remastering的过程并不廉价。在重新配置的过程中,GRD会被锁住,这个操作可能需要好几秒的时间,在这时间内instance也是被锁住的。虽然10gR2推出了并行重配置(parallel reconfiguration)(通过_rcfg_parallel_replay初始化参数控制)使用所有LMS进程来完成重配置,但是几秒钟的系统冻结在很多环境中还是完全不能被接受的。

    3.建议将LMS进程保持在较低的个数(最多3-5),但是如果降低LMS进程数目,那么实例重配置的有效并行度也会降低。

    4.对于较繁忙的环境来说,触发remastering事件的默认参数值通常过低,因此导致了频繁的对象remastering。在EBS环境中,对于manager的配置稍稍处理不善就可能导致大量的重配置问题。

     

    Parameters, views and internals

    有些参数控制了remastering行为,并没有很好的文档说明。我的测试过程也并不非常准确。 但是这些参数还是能大概看出内部是如何工作的。这些参数只对10gR2以后版本生效,在11g中就换了一套参数。

    x$object_affinity_statistics维护对象和对象上的OPENs统计信息。很有必要理解OPEN和buffer access之间的区别。 如果cache中的数据块已经处于非常适合的模式,就没有必要在该块上打开BL锁。所以如果会话重复访问同一个数据块而不请求额外的请求锁,那么计数器就不会增加。因此所谓OPEN就是某一刻的时间帧内对于BL锁的请求计数。

    LCK0进程维护着这些对象的affinity统计信息。如果一个实例比另一实例在某一对象上多打开了50个open(由_gc_affinity_limit参数控制),那么该对象将成为remastering候选者。该对象被放入队列,LMD0进程读取队列,开始GRD冻结。LMON进程协同LMS进程一起执行buffer cache locks的重配置。所有的这些动作都可以在LMD0/LMON trace文件中找到。初始化参数_gc_affinity_time控制队列的检查间隔,以确认remastering是否要触发,默认值是10分钟。

    如果想只有那些有很高的BL锁请求的对象才应该被放入队列并被remastering。可以修改另一个参数_gc_affinity_minimum,只有超过该参数定义的 “每分钟动态affinity活动的最小数量”的对象才会成为候选者而发生remastering。默认值是2500,我认为这在繁忙的系统中有些低。(在11g中,默认值是1500,更低)

    LMD0 trace文件中的以下几行表示LMD0进程正在读取请求队列:
    * kjdrchkdrm: found an RM request in the request queue
      Transfer pkey 6589904 to node 3
    *** 2009-10-12 11:41:20.257
    

    How bad can it get?
    Remastering问题会影响性能。以下AWR报告显示了DRM重配置问题导致的实例冻结。同样类型的冻结在其它的所有节点上也都可以看见。gc buffer busy等待只是DRM冻结的副作用(不是总是这个原因,但是在这个例子是这样)。

    Top 5 Timed Events                                         Avg %Total
    ~~~~~~~~~~~~~~~~~~                                        wait   Call
    Event                                 Waits    Time (s)   (ms)   Time Wait Class
    ------------------------------ ------------ ----------- ------ ------ ----------
    gc buffer busy                    1,826,073     152,415     83   62.0    Cluster
    CPU time                                         30,192          12.3
    enq: TX - index contention           34,332      15,535    453    6.3 Concurrenc
    gcs drm freeze in enter server       22,789      11,279    495    4.6      Other
    enq: TX - row lock contention        46,926       4,493     96    1.8 Applicatio
    

    在同一时刻,DRM大量发生,导致了重复的DRM冻结、实例重配置,从而引发严重的性能问题。

    * received DRM start msg from 2 (cnt 5, last 1, rmno 404)
    Rcvd DRM(404) Transfer pkey 1598477 from 3 to 2 oscan 1.1
    Rcvd DRM(404) Dissolve pkey 6100030 from 2 oscan 0.1
    Rcvd DRM(404) Dissolve pkey 5679943 from 2 oscan 0.1
    Rcvd DRM(404) Transfer pkey 6561036 from 0 to 2 oscan 1.1
    Rcvd DRM(404) Transfer pkey 5095243 to 2 oscan 0.1
    

    A small test case 
    我们来看一个测试,观察一下DRM的产生。使用了索引读路径的查询从一个大索引中读取了几乎所有数据块。

    Session #1:
    select data_object_id from dba_objects where object_name='WMS_N1';
    DATA_OBJECT_ID
    -------------
    6099472
    
    #还没有affinity统计信息
    select * from x$object_affinity_statistics where object=6099472;
    no rows selected.
    
    #执行高代价的查询语句
    select /*+ index(a WMS_N1) */ count(*) from big_table1 a;
    
    Session #2: 观察DRM表:
    #DRM字段现在是409,。将持续观察这个数值。在这个视图中还有其它比较有趣的字段。
    select drms from X$KJDRMAFNSTATS;
    DRM
    ----
    409
    
    #观察到自从会话#1开始运行在该索引上已经有23442个OPENs
    select * from x$object_affinity_statistics where object=6099472;
    ADDR                   INDX    INST_ID     OBJECT       NODE      OPENS
    ---------------- ---------- ---------- ---------- ---------- ----------
    FFFFFFFF7C05BFA8         14          1    6099472          1      23442
    
    #该对象上还没有发生mastering
    select * from v$gcspfmaster_info where object_id=6099472;
    no rows selected
    
    #几秒后,OPENs计数从23442上升到33344
    select * from x$object_affinity_statistics where object=6099472;
    ADDR                   INDX    INST_ID     OBJECT       NODE      OPENS
    ---------------- ---------- ---------- ---------- ---------- ----------
    FFFFFFFF7C05BFA8         16          1    6099472          1      33344
    
    #该对象上还没有发生mastering select * from v$gcspfmaster_info where object_id=6099472; no rows selected #让人诧异,会话#1还在运行,OPENs计数忽然清零即使DRM还未发生过 REM OPENs从0又升到1229因为会话#1还在运行 ADDR INDX INST_ID OBJECT NODE OPENS ---------------- ---------- ---------- ---------- ---------- ---------- FFFFFFFF7C05BFA8 0 1 6099472 1 1229 #大约10分钟以后,remastering发生了。DRMS从409上升到411。 select drms from X$KJDRMAFNSTATS; DRM ---- 411 #该索引的remastering发生了。现在该对象的属主是0,也就是实例1 select * from v$gcspfmaster_info where object_id=6099472; FILE_ID OBJECT_ID CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT ---------- ---------- -------------- --------------- ------------ 0 6099472 0 32767 1 REM OPENs还在上升,但是remastering已经发生了。 select * from x$object_affinity_statistics where object=6099472; ADDR INDX INST_ID OBJECT NODE OPENS ---------------- ---------- ---------- ---------- ---------- ---------- FFFFFFFF7C05AF78 2 1 6099472 1 42335 FFFFFFFF7C05AF78 3 1 6099472 2 1 #LMON trace文件也指出pkey的传递。注意pkey和object_id是相同的。 *** 2010-03-23 10:41:57.355 Begin DRM(411) - transfer pkey 6099472 to 0 oscan 0.0 ftd received from node 1 (4/0.30.0) all ftds received #几秒后,OPENs被再次重置。 select * from x$object_affinity_statistics where object=6099472; ADDR INDX INST_ID OBJECT NODE OPENS ---------------- ---------- ---------- ---------- ---------- ---------- FFFFFFFF7C05BFA8 0 1 6099472 1 7437 #属主仍然是实例1。 select * from v$gcspfmaster_info where object_id=6099472; FILE_ID OBJECT_ID CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT ---------- ---------- -------------- --------------- ------------ 0 6099472 0 32767 1

    测试表明,该索引上发生了大量的BL锁请求,之后对象被remastering。

    undo and affinity
    回滚段的Mastering和其它段不同。对于非回滚段而言,一个段上的所有数据块通过哈希算法被分散在各个实例间。只有在经过大量的BL锁请求以后,段才会被mastering。但是对于回滚段而言,激活了一个回滚段的实例立刻成为该段的属主。这是合乎情理的,因为在大多数情况下回滚段将会被打开这个segment的实例使用。初始化参数_gc_undo_affinity控制这种动态undo remastering动作是否发生。

    回滚段没有真正的object_id,所以使用4294950912作为虚拟object_ids的基准值。比如说,回滚段1(usn=1)的object_id是4294950913,回滚段2(usn=2)的object_id就是4294950914,依次类推。【4294950912 = power(2,32) – power (2,14) = xFFFFC000】

    select object_id, object_id-4294950912 usn, current_master, previous_master,remaster_cnt  from v$gcspfmaster_info where object_id>4294950912;
    
     OBJECT_ID        USN CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT
    ---------- ---------- -------------- --------------- ------------
    4294950913          1              0           32767            1
    4294950914          2              0           32767            1
    4294950915          3              0           32767            1
    4294950916          4              0           32767            1
    4294950917          5              0           32767            1
    4294950918          6              0           32767            1
    4294950919          7              0           32767            1
    4294950920          8              0           32767            1
    4294950921          9              0           32767            1
    4294950922         10              0           32767            1
    4294950923         11              1           32767            1
    4294950924         12              1           32767            1
    4294950925         13              1           32767            1
    ...
    
    REM 注意usn 0在两个实例中都存在,这是系统回滚段。
    REM 下面结果显示,头10个回滚段被node1掌控,而接下来的3个被实例2掌控。
    select inst_id, usn, gets from gv$rollstat where usn <=13 order by inst_id, usn;
       INST_ID        USN       GETS
    ---------- ---------- ----------
             1          0       3130
             1          1     108407
             1          2      42640
             1          3      43985
             1          4      41743
             1          5     165166
             1          6      43485
             1          7     109044
             1          8      23982
             1          9      39279
             1         10      48552
             2          0       4433
             2         11     231147
             2         12      99785
             2         13      1883
    

    Manual remastering

    你可以使用oradebug命令来手动remaster一个对象:

    oradebug lkdebug -m pkey 这会将一个对象remaster请求放入队列。LMD0和LMON进程会完成这个请求。

    *** 2010-01-08 23:25:54.948
    * received DRM start msg from 1 (cnt 1, last 1, rmno 191)
    Rcvd DRM(191) Transfer pkey 6984154 from 0 to 1 oscan 0.0
     ftd received from node 1 (8/0.30.0)
     ftd received from node 0 (8/0.30.0)
     ftd received from node 3 (8/0.30.0)
    

    当前属主是从0开始计数的。

    SQL> select * from v$gcspfmaster_info where object_id=6984154;
       FILE_ID  OBJECT_ID CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT
    ---------- ---------- -------------- --------------- ------------
             0    6984154              1               0            2
    
    SQL> oradebug lkdebug -m pkey 6984154
    Statement processed.
    
    SQL>  select * from v$gcspfmaster_info where object_id=6984154;
    
       FILE_ID  OBJECT_ID CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT
    ---------- ---------- -------------- --------------- ------------
             0    6984154              2               1            3
    

    Summary

    总结一下,remarstering是个很好的功能。不过遗憾的是,有时候会成为它负面效果的受害者。所以,如果碰到remastering引起的问题,不要直接就禁用它,而是应该去看看能否调优那些参数从而控制remastering事件。

    如果你仍然想完全禁用DRM,那么我建议设置_gc_affinity_limit和_gc_affinity_minimum参数到一个较高值,比如说1千万。将参数_gc_affinity_time设置为0也可以完全禁用DRM,但是这也意味着再也无法手工remaster对象了。另外,Arup也提到如果DRM被禁用那么x$object_affinity_statistics表也不会再被维护。

    再次提醒,这些是隐含参数。在你修改这些参数之前确认Oracle Support同意。

    Update 1:
    从11g开始,affinity管理更名为policy管理(策略管理)。比如说,x$object_affinity_statistics表改名为x$object_policy_statistics。

    与之相似的,初始化参数也发生了改变:参数_gc_affinity_limit改名为_gc_policy_limit;参数_gc_affinity_time改名为_gc_policy_time;

    出现了一个新的视图v$policy_history,其中所有policy_event = ‘initiate_affinity’的记录都是与DRM事件相关的。

    本blog的其它部分仍然没问题,除了默认的_gc_policy_limit参数值降低为1500,这意味着,在理论上,11g可能会产生更多的DRM事件。

    >  select * from  v$policy_history
       INST_ID POLICY_EVENT         DATA_OBJECT_ID TARGET_INSTANCE_NUMBER  EVENT_DATE
    ---------- -------------------- -------------- ----------------------  --------------------
             2 glru_on                           0                      1  10/15/2010 10:58:28
             2 glru_on                           0                      1  10/15/2010 11:21:32
             2 initiate_affinity             74809                      1  10/15/2010 13:27:44
    

    补充:

    BL锁:buffer lock
    GRD:Global Resource Directory,GRD分散在集群中所有节点
    LMS:oracle 10g中的定义:Global Cache Service (LMS) - In a Real Application Clusters environment, this process manages resources and provides inter-instance resource control
    LCK0:Instance Enqueue Background Process。管理全局队列请求和跨节点广播
    LMD0:Global Enqueue Service Daemon 0 Process。管理来自其他实例的远程资源请求
    LMON:Global Enqueue Service Monitor Process。监控rac集群,管理全局资源
    LMSn: Global Cache Service Process。

    参考文章:

     
     
  • 相关阅读:
    【转载】jquery取得iframe元素的方法
    【转载】URL重写相关
    【转载】PHP程序员突破成长瓶颈
    【转载】是什么浪费了我的上网时间
    信息化时代下的我们弄潮儿
    如何减小与“大牛”的差距
    servlet应用之cookies&session操作
    Servlet简介及工作原理
    深入学习Tomcat自己动手写服务器(附服务器源码)
    servlet过滤器
  • 原文地址:https://www.cnblogs.com/abclife/p/5311887.html
Copyright © 2020-2023  润新知