oracle获取序列跳号,ORACLE SEQUENCE跳号总结

在ORACLE数据库中,序列(SEQUENCE)是使用非常频繁的一个数据库对象,但是有时候会遇到序列(SEQUECNE)跳号(skip sequence numbers)的情形,那么在哪些情形下会遇到跳号呢?

事务回滚引起的跳号

不管序列有没有CACHE、事务回滚这种情况下,都会引起序列的跳号。如下实验所示:

SQL> create sequence my_sequence2  start with 13  increment by 14  maxvalue 999995  nocache;Sequence created.SQL>  create table test(id number(10), name varchar2(32));Table created.SQL> insert into test2  select my_sequence.nextval , 'kerry' from dual;1 row created.SQL>SQL> rollback;Rollback complete.SQL> select my_sequence.nextval from dual;NEXTVAL----------3SQL>

38f8c46a66ab526d34856bac4602acb4.png

并发访问序列引起的跳号

并发访问序列引起的跳号,其实不算真正的跳号,而只是逻辑跳号,只是序列值被其它并发会话使用了。我们来构造一起并发访问序列引起的跳号,我们开启两个会话窗口,循环获取序列的值,模拟并发出现的场景。

会话窗口A:

exec dbms_lock.sleep(2); --延迟2秒执行,根据你实验情况调整/beginfor i in 1 .. 2000 loopdbms_output.put_line(my_sequence.nextval);end loop;end;/

会话窗口B:

spool test.txt;beginwaitfor delay '00:00:10';for i in 1 .. 2000 loopdbms_output.put_line(my_sequence.nextval);end loop;end;/spool off;

如下所示,我构造的实验当中,你会看到序列的跳号情况。

a1e1b3207df28d87783c8c57b83992b6.png

FLUSH SHARED_POOL会导致CACHE的序列跳号

实验测试如下所示(序列的CACHE值必须大于0),当然正常情况下,很难遇到这种情况。

SQL> select test.my_sequence.nextval from dual;NEXTVAL----------17004SQL> alter sequence test.my_sequence cache 40;Sequence altered.SQL> select test.my_sequence.nextval from dual;NEXTVAL----------17005SQL> alter system flush share_pool;alter system flush share_pool*ERROR at line 1:ORA-02000: missing SHARED_POOL/BUFFER_CACHE/GLOBAL CONTEXT keywordSQL> alter system flush shared_pool;System altered.SQL> select test.my_sequence.nextval from dual;NEXTVAL----------17045

d6d2d5a8152bd9ebe92a22ca07f9fcde.png

数据库实例异常关闭导致跳号

如下实验所示,当数据库使用shutdown abort命令关闭后,重新启动实例,序列缓存在shared pool里面没有用过的值都没有了。一下子从17045跳到17085

SQL> select test.my_sequence.currval from dual;CURRVAL----------17045SQL> select object_id from dba_objects where object_name=upper('my_sequence');OBJECT_ID----------97760SQL> select increment$, minvalue, maxvalue,highwater, cache2  from seq$ where obj#=97760;INCREMENT$   MINVALUE   MAXVALUE  HIGHWATER      CACHE---------- ---------- ---------- ---------- ----------1          1      99999      17085         40SQL> shutdown abort;ORACLE instance shut down.SQL> startup;ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instanceORACLE instance started.Total System Global Area 1620115456 bytesFixed Size                  2213816 bytesVariable Size            1258293320 bytesDatabase Buffers          352321536 bytesRedo Buffers                7286784 bytesDatabase mounted.Database opened.SQL> select test.my_sequence.currval from dual;select test.my_sequence.currval from dual*ERROR at line 1:ORA-08002: sequence MY_SEQUENCE.CURRVAL is not yet defined in this sessionSQL> select test.my_sequence.nextval from dual;NEXTVAL----------17085SQL>

另外,我们也来看看正常关闭数据库的情况下,序列会不会出现跳号,我们采用10046跟踪事件,看看正常数据库关闭情况下,会对序列做一些啥操作

SQL> select test.my_sequence.nextval from dual;NEXTVAL----------17085SQL> alter session set events '10046 trace name context forever, level 4';Session altered.SQL> shutdown immediate;Database closed.Database dismounted.ORACLE instance shut down.SQL> startupORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instanceORACLE instance started.Total System Global Area 1620115456 bytesFixed Size                  2213816 bytesVariable Size            1258293320 bytesDatabase Buffers          352321536 bytesRedo Buffers                7286784 bytesDatabase mounted.Database opened.SQL> select test.my_sequence.currval from dual;select test.my_sequence.currval from dual*ERROR at line 1:ORA-08002: sequence MY_SEQUENCE.CURRVAL is not yet defined in this sessionSQL> select test.my_sequence.nextval from dual;NEXTVAL----------17086SQL>

Trace文件中有更新seq$数据字典表,如果你看过我这篇文章ORACLE中seq$表更新频繁的分析,基本上就知道其实seq$中维护的是序列的一些信息。通过跟踪文件,我们知道在数据库正常关闭的情况下,会触发一个update seq$的操作,把当前的sequence.nextval的值更新到seq$.highwater中,从而使得sequence在有cache的情况下,数据库正常关闭未出现nextval跳跃(currval也同样不跳跃);而在数据库异常关闭之时,数据库不能及时将sequence.nextval更新到eq$.highwater从而引起sequence cache中的值丢失,从而可能出现了sequence使用cache导致跳跃的情况

=====================PARSING IN CURSOR #25 len=129 dep=1 uid=0 oct=6 lid=0 tim=1504236336294194 hv=2635489469 ad='bf780410' sqlid='4m7m0t6fjcs5x'update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1END OF STMTPARSE #25:c=0,e=21,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1935744642,tim=1504236336294194BINDS #25:Bind#0oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=bf45ca48  bln=24  avl=02  flg=09value=1Bind#1oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=bf45ca5a  bln=24  avl=02  flg=09:/17086Bind#3oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=2b7d80f57350  bln=24  avl=01  flg=05value=0Bind#4oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=2b7d80f57320  bln=24  avl=01  flg=05value=0Bind#5oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=bf47b85e  bln=24  avl=02  flg=09value=40Bind#6oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=bf47b870  bln=24  avl=04  flg=09value=17086Bind#7oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=01 csi=873 siz=32 off=0kxsbbbfp=bf47b882  bln=32  avl=32  flg=09value="--------------------------------"Bind#8oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=2b7d80f572f0  bln=24  avl=02  flg=05value=8Bind#9oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0kxsbbbfp=2b7d80f57380  bln=22  avl=04  flg=05value=97760EXEC #9:c=999,e=709,p=0,cr=1,cu=2,mis=0,r=1,dep=1,og=4,plh=1935744642,tim=1504236336297033CLOSE #9:c=0,e=2,dep=1,type=3,tim=1504236336297058

mealink上提到了使用dbms_shared_pool.keep将对象在锁定在shared pool 中,永远不释放。这样可以防止FLUSH SHARED POOL导致序列跳号,但是这个无法避免数据库异常关闭或CRASH引起的跳号

SQL> select test.my_sequence.currval from dual;CURRVAL----------17086SQL> exec dbms_shared_pool.keep('test.my_sequence','q');PL/SQL procedure successfully completed.SQL> alter system flush shared_pool;System altered.SQL> select test.my_sequence.currval from dual;CURRVAL----------17086SQL> shutdown abortORACLE instance shut down.SQL> startupORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instanceORACLE instance started.Total System Global Area 1620115456 bytesFixed Size                  2213816 bytesVariable Size            1258293320 bytesDatabase Buffers          352321536 bytesRedo Buffers                7286784 bytesDatabase mounted.Database opened.SQL> select test.my_sequence.nextval from dual;NEXTVAL----------17126

b411abfa886c53853f60b9af5f5889bf.png

其实如果业务允许,单号出现跳号也无所谓的情形最好,如果碰到业务要求绝对不能出现单号出现跳号的情况,那么就不能使用序列号了,就必须使用其它替代方案,此处不做展开说明!

参考资料:

fcde9e97bf41582984fc906146a0d1c9.png

Sequence Number Generator Generating Numbers With Gaps (文档 ID 470784.1)

Using the Oracle DBMS_SHARED_POOL Package (文档 ID 61760.1)

http://www.xifenfei.com/2015/04/%E6%AD%A3%E5%B8%B8%E5%85%B3%E9%97%AD%E6%95%B0%E6%8D%AE%E5%BA%93sequence-cache%E4%B8%8D%E4%B8%BA0-sequence%E4%B8%8D%E8%B7%B3%E8%B7%83.html

内容来源于网络如有侵权请私信删除

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值