ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Oracle 10g RAC中的DRM

Oracle 10g RAC中的DRM

原创 Linux操作系统 作者:wei-xh 时间:2011-07-26 14:22:40 0 删除 编辑

http://blog.china.com/u/071030/89253/201007/6618907.html

 

在RAC环境中,Oracle使用GRD(Global Resource Service)来记录各个RAC节点的资源信息,具体通过GCS(Global Cache Service)和GES(Global Enqueue Service)这两个服务进行管理。
      由于在RAC中每个节点都有自己的SGA和buffer cache,为了保证Cache资源的一致性和提高性能,GCS和GES会指定RAC中的一个instance来管理Cache,这个节点这时就是Resource Master。
      在10g以前,Cache资源是不能在各个节点间移动的,除非重启或者某节点因为其他异常被RAC驱逐等情况。而10g的DRM就解决了这个问题,它可以保证cache能够被remaster到频繁访问这部分数据的节点上,从而提高RAC的性能。DRM的全称是Dynamic Resource Mastering,metalink上的Doc ID:  390483.1文档详细介绍了DRM的信息。 

      从理论上讲,利用此项技术,非master节点对所需资源有频繁访问需求时,可以提升为master节点,从而减少大量后续的跨节点资源访问需求。
      但是,首先从根本上说,一个好的RAC应用设计,本就应该极尽所能的取避免同一资源的多节点访问,如果不存在同一资源的多节点访问,则DRM所要解决的问题,就根本不存在。其次,DRM本身是需要消耗资源的,并且存在诸多bug,对于一个设计较差的系统而言,频繁的DRM,也会引发Libary cache lock而导致实例挂住。
      更严重的,在10.2.0.3系统上,曾经遇到一个case,电信行业的巨型数据库,rac的2号节点由于批量处理作业在非业务时间段,首先cache了一张40G的表,而到了业务时间段后,rac的1号节点的OLTP业务需要频繁访问该表,此时,故障发生了,由于DRM的介入,2号节点开始将内存内的40Gcache数据向1号节点传输,心跳网段千兆带宽被耗尽,RAC陷入僵死阶段,足足维持了40分钟。
      事后检查网络流量图,该时段内,私有网络流量持续保持在90M/s的峰值水平。
      根据metalink确认,该问题确实由DRM机制引起,最终解决方案,使用隐含参数,将DRM特性屏蔽:
_gc_affinity_time=0  
_gc_undo_affinity=FALSE 

      因此,从根本上来说,drm的出现,只是在理论上的一种缓解,而并不能在实际的大型应用中发挥其作用。就类似于Oracle自己针对RAC推出的自动负载平衡一样,只是一种看起来很美的东西,如果真的有人用了,呵呵,那就只能等死吧。或许压力极小的数据库无所谓,但我没遇到过,话又说回来,压力极小,又何必上RAC呢。
ORACLE中所有的数据都是以块的方式存储的,那么在RAC环境下,一个块就会存在被多个节点读写的情况。这个时候如果有一个节点需要对这个块进行读写,那么首先可能就需要知道这个块的信息,比如这个块是否在内存中、是否是脏块、是否需要构造一致性读、块上是否有其他人对其中某行进行了锁定等等,那么这些块的信息就需要而且只能由一个节点来进行管理,其他节点需要知道这个块的信息的时候,就去查询GRD(Global Resource Directory),GRD告知你谁是这个块的MASTER,然后你就可以去MASTER那里请求对资源的访问。假如这个资源是MASTER在节点1,而节点2需要频繁的访问这个块,那么就需要非常多的请求MASTER的过程,这个过程要通过心跳网络来完成,速度比直接访问内存慢N多倍,所以效率就会有问题。那么ORACLE就会把这个块的MASTER权限从节点1交给节点2来提高效率。DRM是10G才出现的功能,并且在10.1和10.2中实现的精度是不一样的。10.1是以FILE为单位的,10.2是以SEGMENT为单位的。


跟BUFFER CACHE的访问机制类似,ORACLE会使用HASH的方式来决定每个BLOCK的MASTER是哪个节点,默认情况下HASH的BUCKET是128,也就是说ORACLE按照连续128个BLOCK在一个节点,然后接下来的128个BLOCK在另外一个节点这样的机制来进行平均分配块的MASTER。这个BUCKET可以通过隐含参数_lm_contiguous_res_count来进行修改。

每个BLOCK是被哪个节点MASTER的,可以通过X$KJBR.KJBRNAME来查看,这个字段的记录不那么直观,那么可以通过下面两个函数来进行转换,得到MASTER的是哪个文件的哪个块。
CREATE OR REPLACE FUNCTION GET_FILE_NUMBER(P_RESOURCE_NAME VARCHAR2)
RETURN INTEGER IS
POS1 INTEGER := INSTR(P_RESOURCE_NAME, 'x', 1, 2);
POS2 INTEGER := INSTR(P_RESOURCE_NAME, ']', 1, 2);
S VARCHAR2(30) := SUBSTR(P_RESOURCE_NAME, POS1 + 1, POS2 - POS1 - 1);
BEGIN
RETURN TO_NUMBER(S, 'XXXXXXXX') / 65536;
END;
/
CREATE OR REPLACE FUNCTION GET_BLOCK_NUMBER(P_RESOURCE_NAME VARCHAR2)
RETURN INTEGER IS
POS1 INTEGER := INSTR(P_RESOURCE_NAME, 'x', 1, 1);
POS2 INTEGER := INSTR(P_RESOURCE_NAME, ']', 1, 1);
S VARCHAR2(30) := SUBSTR(P_RESOURCE_NAME, POS1 + 1, POS2 - POS1 - 1);
BEGIN
RETURN TO_NUMBER(S, 'XXXXXXXX');
END;
/

然后使用
SELECT GET_FILE_NUMBER(KJBRNAME), GET_BLOCK_NUMBER(KJBRNAME) FROM X$KJBR;
到每个节点查询,从返回结果就可以知道这个节点MASTER了哪些BLOCK。

如果想手工的把一个SEGMENT的所有块都MASTER到一个节点,首先要知道这个SEGMENT所对应的OBJECT的DATA_OBJECT_ID,然后使用:
oradebug lkdebug -m pkey DATA_OBJECT_ID

如果想使得所有块的MASTER回到初始的根据HASH分配的状态,那么使用:
oradebug lkdebug -m dpkey DATA_OBJECT_ID

GV$GCSPFMASTER_INFO视图记录了REMASTER的结果,其中FILE_ID表示是哪个文件,OBJECT_ID表示是哪个对象,CURRENT_MASTER表示当前的MASTER,PREVIOUS_MASTER表示之前这个资源是MASTER在哪个节点上的,REMASTER_CNT表示REMASTER的次数(不过这个数字好像不那么靠谱)。其中如果PREVIOUS_MASTER为32767,表示这个资源一上来就MASTER在这个节点上的,没经过REMASTER的。

另外三个视图也记录了REMASTER的相关信息:
X$KJDRMREQ:Dynamic Remastering Requests
X$KJDRMAFNSTATS:File Remastering Statistics
X$KJDRMHVSTATS:Hash Value Statistics

LMD进程负责完成DRM的过程,所以DRM的TRACE会写在LMD进程的TRACE文件中。

DRM提高效率的同时也带来一堆问题,在整个10.2.0.2版本之前,DRM都不那么稳定,ORACLE也不推荐使用(但这又是缺省在使用的功能)严重的会导致系统HANG住。可以通过下面两个隐含参数来禁止DRM的发生:
_gc_undo_affinity=FALSE
_gc_affinity_time=0

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-703115/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE组成员,DBGeeK用户组发起人。曾在DTCC、ORACLE技术嘉年华、Gdevops等公开场合做过数据库技术专题分享,2017年应Oracle邀请在世界最大的数据库会议OOW上做技术分享。组织翻译了《拨云见日,解密Oracle ASM内核》一书。

注册时间:2009-07-04

  • 博文量
    422
  • 访问量
    2340997