oracle为了管理Sequence使用了以下三种锁:
row cache lock :在调用Sequnece.nextval过程中.将数据字典信息进行物理修改时获取.赋予NOCACHE属性的Sequence上发生。
enq:SQ-contention(SQ锁):在内存上缓存(cache)的范围内.调用 Sequence.nextval 期间拥有此锁.赋予了CACHE厲性的Sequence上发生。
DFS lockhandle(SV锁):RAC上节点之间序得到保陣的悄况下.调用Sequence.nextval期间拥有赋予了CACHE+ORDER厲性的Sequence上发生。
通过v$lock_type可以看到关于该锁的描述:

select*fromv$lock_typeawherea.TYPEin('SQ','SV')TYPE:SQNAME:SequenceCacheID1_TAG:object#ID2_TAG:0IS_USER:NODESCRIPTION:Locktoensurethatonlyoneprocesscanreplenishthesequencecache-----------------TYPE:SVNAME:SequenceOrderingID1_TAG:object#ID2_TAG:0IS_USER:NODESCRIPTION:LocktoensureorderedsequenceallocationinRACmode


赋予了 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以上的较大值。

测试:

1.创建seq:dropsequenceapp.info_seq;createsequenceapp.info_seqstartwith1maxvalue999999999999999999999999999minvalue1nocycleorder;2.创建过程createorreplaceprocedurepseq(anumber)asnext_sqlnumber;beginforxin1..aloopexecuteimmediate'selectapp.info_seq.nextvalfromdual'intonext_sql;endloop;end;/3.在session1、sesseion2同时执行:execpseq(400000)4.等待事件:SQL>selecta.EVENT,a.SID,a.P1,a.P2fromv$sessionawherea.WAIT_CLASS#<>6;EVENTSIDP1P2-------------------------------------------------------------logfileparallelwrite112144enq:SQ-contention36139781735065009enq:SQ-contention37139781735065009SQL*Netmessagetoclient6614136975361SQL>selectchr(bitand(p1,-16777216)/16777215)||2chr(bitand(p1,16711680)/65535)"Lock",3bitand(p1,65535)"Mode"4fromv$session5whereevent='enq:SQ-contention';LockMode------------------SQ6SQ6ModeValueDescription1Nullmode2Sub-Share3Sub-Exclusive4Share5Share/Sub-Exclusive6ExclusiveSQL>selectd.owner,d.object_name,d.object_typefromdba_objectsdwhereobject_idin(2selectp2fromv$sessionawherea.WAIT_CLASS#<>6andevent='enq:SQ-contention');OWNEROBJECT_NAMEOBJECT_TYPE------------------------------------------APPINFO_SEQSEQUENCE



另外,偶尔一次性同时创建许多会话时,有时会发生enq:SQ-contention等待事件。其理由是V$SESSION.AUDSID(auditingsessionid)列值是利用Sequence创建的。Oracle在创建新的会话后,利用名为SYS.AUDSES$的Sequence的nextval,创建AUDSID值。SYS.AUDSES$Sequence的CACHE大小的缺省值设定为20。许多会话同时连接时,可以将SYS.AUDSES$Sequence的CACHE大小扩大至1000,以此可以解决enq:SQ-contention等待问题。10g下默认20,11g下默认为10000。
RAC上创建Sequence时,在赋予了CACHE属性的状态下,若没有赋予ORDER属性,则各节点将会把不同范围的Sequence值CACHE到内存上。比如,拥有两个节点的RAC环境下,创建CACHE值为100的Sequence时,1号节点使用1-100.2号节点使用101-200。若两个节点之间都通过递增方式使用quence,必须赋予如下ORDER属性。

SQL>createsequenceordereQuencecacke100order;


如果是已赋予了CACHE+ORDER属性的Sequence,Oracle使用SV锁进行行同步。即,对赋予了ORDER属性的Sequence调用nextval时,应该以SSX模式拥有SV锁。在获取SV锁过程中,如果发生争用时,不是等持rowcachelock事件或enq:SQ-contention事件,而是等待名为DFSlockhandle事件。正因如此,V$EVENT_NAME视图上不存在类似enq:SQ-contention的事件。DFSIockhandle事件是在OPS或RAC环境下,除了高速缓冲区同步之外,还有行高速缓冲区或库高速缓冲区的为了同步获取锁的过程中等待的事件。若要保降多个节点之间Sequence顺序,应该在全局范围内获得锁,在此过程中会发生DFSlockhandle等待。在获取SV锁的过程屮发生的DFSlockhandle等待事件的PI、P2值与enq:SQ-contertion等待事件相同P1=mode+namespace、P2=object#),因此从PI值能确认是否是SV锁,通过P2值可以确认对哪些Sequenced生过等待。SV锁争用问题发生时的解决方法与SQ锁的怙况相同,就是对CACHE值进行适当调整,这也是唯一的方法。
RAC等多节点环境下,Sequence的CACHE值给性能带来的影响比单节点更加严重。因此,尽量赋予CACHE+NOORDER属性,并要给予足够大的CACHE值。如果要求保持顺序,必须赋予CACHE+ORDER属性。但这时为了保障顺序,实例之间不断发生数据的交换。因此,赋予了NOORODER属性的时候相对性能稍差。

根据创建Sequence时赋予的属性,等侍事件的结果如下:

NOCACHE:rowcackelockCACHE+NOORDER:enQ:SQ-contentionCACHE+ORDER(RAC):DTSlockHandle


如果序列作为索引中的一部分,高并发环境会导致索引分裂问题的发生,常见的等待事件为:enq: TX - index contention