ORACLE RAC环境下读取序列乱序问题

在数据库部署了RAC环境之后,偶尔会出现从Oracle Sequence所取出来的数是混乱的,比如第二次比第一次所取的数要小。这样当程序的逻辑依赖于ID的大小来排序时,就会产生系统混乱。


其实问题是出在数据库是个RAC环境,序列是被共享的,序列默认是有缓存的。假设RAC上的两个节点上序列缓存设为20,第一个节点上缓存1-20,第二个节点缓存了21-40,当从不同节点来进行对sequence取值的时候,从第二个节点上取的值就会比从第一个节点上取的要大。而且默认序列都是noorder的。因为很有可能出现这种情况。


具体方法有两个:

1. 设置cache为空

2. 创建序列的时候设置为order,即采用cache + order

 

sequence创建方法:

CREATE SEQUENCE [schema.]sequence  
    [INCREMENT BY integer]  
    [START WITH integer]  
    [MAXVALUE integer | NOMAXVALUE]  
    [MINVALUE integer | NOMINVALUE]  
    [CYCLE | NOCYCLE]  
    [CACHE integer | NOCACHE]  
    [ORDER | NOORDER]  

 

Oracle下关于Sequence的使用有三种情况:

1. cache + noorder

2. nocache

3. cache + order

 

Oracle为了管理sequence使用了以下三中锁

1row cache lock

       在调用sequence.nextval过程中,将数据字典信息进行物理修改时获取,赋予了nocache属性的sequence上发生。

2SQ -- enq: SQ

       在内存上缓存(cache)范围内,调用sequence.nextval期间拥有此锁,赋予了cache+noorder 属性的sequence上发生。

3SV -- DFS lock handle  

       RAC上节点之间顺序得到保障的情况下,调用sequence.nextval期间获得,赋予了cache+order属性的sequence上发生。

    

     赋予了CACHE属性的sequence调用nextval期间,应该以SSX模式获得SQ锁,许多会话同时为了获取SQ锁而发生争用过程中,若发生争用,则等待enq:SQ-contention.

       enq:SQ-contention事件的P2值是sequence的object ID,因此,若利用P2值与DBA_OBJECTS的结合,就可以知道对哪个、 Sequence发生了等待对象。

    

     创建Sequence赋予的CACHE值较小时,有enq:SQ-contention等待增加的趋势,CACHE值较小,内存上事先CACHE的值很快被耗尽,这时需要将数据字典信息物理修改,再次执行CACHE的工作,在此期间,因为一直要拥有SQ锁,相应的Enq:SQ-contention事件的等待时间也会延长,很不幸的是,在创建Sequence时,将CACHE值的缺省值设定为较小20,因此创建使用量最多的Sequence时,CACHE值应该取1000以上的较大值。

    

     偶而一次性同时创建许多会话,有时会发生enq:SQ-contention等待事件,其理由是V$SESSION.AUDSID(auditing sessionid) 列值是利用Sequence创建的,oracle在创建新的会话后,利用名为SYS.AUDSESS$的sequence的nextval创建AUDSID的值,SYS.AUDSESS$ Sequence的CACHE大小的缺省值设定为 20,许多会话同时连接,可以将SYS.AUDSESS$ sequence的CACHE大小扩大至1000,以此可以解决 enq:SQ-contention等待问题。

    

     RAC上创建Sequence时,在赋予了CACHE属性的状态下:

       (1)若没有赋予ORDER属性,则各节点将会把不同范围的Sequence值CACHE到内存上,比如拥有两个节点的RAC环境下,创建CACHE值为100的 sequence时,1节点会使用1-100,2节点会使用101-200。 使用时从各自节点取sequence。

       (2)若两个节点之间会通过递增的使用sequence,必须赋予如下ORDER属性。

     SQL>Create sequence ordered_sequence cache 100 order;

       在order 的情况下,2个节点取的sequence是递增的。 下文会有示例来说明这两种情况。

 

     如果已赋予CACHE+ORDER属性的sequence, oracle使用SV锁进行行同步,即,对赋予了ORDER属性的sequence调用nextval时,应该以SSX模式拥有SV锁,在获取SV锁过程中,若发生了争用,不是等待ROW CACHE或者是enq:SQ-contention,而是等待名为DFS lock handle事件,正因如此V$EVENT_NAME视图上不存在类似与"enq:SV-contention"

 

       DFS lock handle事件是在OPS或者RAC环境下,除了 高速缓冲区 同步之外,还有 行高速缓冲区 或者 库高速缓冲区 同步获取锁的过程中的等待事件。     若保证全局范围内获得锁,在此过程中会发生DFS look handle等待,在获取SV锁的过程中发生的DFS lock handle等待事件的P1,P2值与enq:SQ-contention等待事件相同(p1=mode+namespace,p2=object#).因此会从P1值能确认是否是SV锁,通过P2可以确认哪些是Sequence发生过等待.

 

       SV锁争用问题发生时的解决办法与SQ锁的情况相同,就是CACHE值进行适当的调整,这也是唯一的方法。


本文转自:http://blog.csdn.net/scorpio3k/article/details/8597965

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值