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

事务回滚引起的跳号

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

SQL> create sequence my_sequence

  2  start with 1

  3  increment by 1

  4  maxvalue 99999

  5  nocache;

 

Sequence created.

 

SQL>  create table test(id number(10), name varchar2(32));

 

Table created.

 

SQL> insert into test

  2  select my_sequence.nextval , 'kerry' from dual;

 

1 row created.

 

SQL> 

SQL> rollback;

 

Rollback complete.

 

SQL> select my_sequence.nextval from dual;

 

   NEXTVAL

----------

         3

 

SQL> 

 

并发访问序列引起的跳号

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

会话窗口A:

exec dbms_lock.sleep(2); --延迟2秒执行,根据你实验情况调整

/

begin

    for i in 1 .. 2000 loop

        dbms_output.put_line(my_sequence.nextval);

    end loop;

end;

/

会话窗口B:

spool test.txt;

begin

    waitfor delay '00:00:10';

    for i in 1 .. 2000 loop

        dbms_output.put_line(my_sequence.nextval);

    end loop;

end;

/

spool off; 

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

FLUSH SHARED_POOL会导致CACHE的序列跳号

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

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17004

 

SQL> alter sequence test.my_sequence cache 40;

 

Sequence altered.

 

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17005

 

SQL> alter system flush share_pool;

alter system flush share_pool

*

ERROR at line 1:

ORA-02000: missing SHARED_POOL/BUFFER_CACHE/GLOBAL CONTEXT keyword

 

 

SQL> alter system flush shared_pool;

 

System altered.

 

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17045

 

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

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

SQL> select test.my_sequence.currval from dual;

 

   CURRVAL

----------

     17045

 

SQL> select object_id from dba_objects where object_name=upper('my_sequence');

 

 OBJECT_ID

----------

     97760

 

SQL> select increment$, minvalue, maxvalue,highwater, cache

  2  from seq$ where obj#=97760;

 

INCREMENT$   MINVALUE   MAXVALUE  HIGHWATER      CACHE

---------- ---------- ---------- ---------- ----------

         1          1      99999      17085         40

 

SQL> shutdown abort;

ORACLE instance shut down.

SQL> startup;

ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance

ORACLE instance started.

 

Total System Global Area 1620115456 bytes

Fixed Size                  2213816 bytes

Variable Size            1258293320 bytes

Database Buffers          352321536 bytes

Redo Buffers                7286784 bytes

Database 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 session

 

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17085

 

SQL> 

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

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17085

 

SQL> 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> startup

ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance

ORACLE instance started.

 

Total System Global Area 1620115456 bytes

Fixed Size                  2213816 bytes

Variable Size            1258293320 bytes

Database Buffers          352321536 bytes

Redo Buffers                7286784 bytes

Database 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 session

 

 

SQL> select test.my_sequence.nextval from dual;

 

   NEXTVAL

----------

     17086

 

SQL> 

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#=:1

END OF STMT

PARSE #25:c=0,e=21,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=1935744642,tim=1504236336294194

BINDS #25:

 Bind#0

  oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=bf45ca48  bln=24  avl=02  flg=09

  value=1

 Bind#1

  oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=bf45ca5a  bln=24  avl=02  flg=09

:/17086                                                                                                                                                                     

 Bind#3

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=2b7d80f57350  bln=24  avl=01  flg=05

  value=0

 Bind#4

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=2b7d80f57320  bln=24  avl=01  flg=05

  value=0

 Bind#5

  oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=bf47b85e  bln=24  avl=02  flg=09

  value=40

 Bind#6

  oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=bf47b870  bln=24  avl=04  flg=09

  value=17086

 Bind#7

  oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=01 csi=873 siz=32 off=0

  kxsbbbfp=bf47b882  bln=32  avl=32  flg=09

  value="--------------------------------"

 Bind#8

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=2b7d80f572f0  bln=24  avl=02  flg=05

  value=8

 Bind#9

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0

  kxsbbbfp=2b7d80f57380  bln=22  avl=04  flg=05

  value=97760

EXEC #9:c=999,e=709,p=0,cr=1,cu=2,mis=0,r=1,dep=1,og=4,plh=1935744642,tim=1504236336297033

CLOSE #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

----------

     17086

 

SQL> 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

----------

     17086

SQL> shutdown abort

ORACLE instance shut down.

SQL> startup

ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance

ORACLE instance started.

 

Total System Global Area 1620115456 bytes

Fixed Size                  2213816 bytes

Variable Size            1258293320 bytes

Database Buffers          352321536 bytes

Redo Buffers                7286784 bytes

Database mounted.

Database opened.

SQL> select test.my_sequence.nextval from dual;

   NEXTVAL

----------

     17126

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

参考资料:

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

ORACLE SEQUENCE跳号总结的更多相关文章

  1. 从SEQUENCE跳号说起

    http://blog.csdn.net/agaric717/article/details/6690890 一个应用上线后发现一个使用SEQUENCE值来生成的主键经常出现断号,而且断号不是一两个, ...

  2. SQL Server解惑——标识列的限制和跳号现象

      1:每个表只能创建一个标识列. 如下测试所示,如果表中有一个标识列,新增一个标识列就会遇到错误"Multiple identity columns specified for table ...

  3. oracle SEQUENCE 创建, 修改,删除

    oracle创建序列化: CREATE SEQUENCE seq_itv_collection            INCREMENT BY 1  -- 每次加几个              STA ...

  4. ORACLE SEQUENCE用法

    引用自: http://www.cnblogs.com/hyzhou/archive/2012/04/12/2444158.html 在oracle中sequence就是序号,每次取的时候它会自动增加 ...

  5. Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍

    引用自 :http://www.2cto.com/database/201307/224836.html   Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍 先假设有这么一个表 ...

  6. 【转】oracle Sequence

    http://blog.csdn.net/zhoufoxcn/article/details/1762351 在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没 ...

  7. ORACLE SEQUENCE 介绍

    在oracle中sequence就是所谓的序列号,每次取的时候它会自己主动添加,一般用在须要按序列号排序的地方.  1.Create Sequence  你首先要有CREATE SEQUENCE或者C ...

  8. ORACLE SEQUENCE用法 (自增长)

    在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没有关系. 1.Create Sequence     首先要有CREATE SEQUENCE或者CREATE ...

  9. ORACLE SEQUENCE的简单介绍

    先假设有这么一个表: create table S_Depart ( DepartId INT not null, DepartName NVARCHAR2() not null, DepartOrd ...

随机推荐

  1. 51nod_1264:线段相交(计算几何)

    题目链接 关于判断线段相交,具体算法见 点击打开链接 ,先进行快速排斥试验,若不能判断出两个线段不相交,再进行跨立试验. //吐槽1,long long 会溢出... //吐槽2,只进行跨立试验的虽然 ...

  2. [luogu]P1352 没有上司的舞会[树形DP]

    本Lowbee第一次写树形DP啊,弱...一个变量写错半天没看出来...... 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点 ...

  3. 采用HTML5之"data-"机制自由提供数据

    周末总是过得很快,又到了跟代码亲密接触的日子,我在北京向各位问好,今天我分享一点关于前端的东西,HTML5之标签"data-*"自定义属性的值传递. 在过去学习JavaScript ...

  4. ES6模板字面量

    前面的话 JS 的字符串相对其他语言来说功能总是有限的,事实上,ES5中一直缺乏许多特性,如多行字符串.字符串格式化.HTML转义等.ES6通过模板字面量的方式进行了填补,模板字面量试着跳出自己JS已 ...

  5. tensorflow softmax应用

    ---恢复内容开始--- 1.softmax函数 2.tensorflow实现例子 #!/usr/bin/env python # -*- coding: utf-8 -*- import tenso ...

  6. KMP算法 --- 在文本中寻找目标字符串

    KMP算法 --- 在文本中寻找目标字符串 很多时候,为了在大文本中寻找到自己需要的内容,往往需要搜索关键字.这其中就牵涉到字符串匹配的算法,通过接受文本和关键词参数来返回关键词在文本出现的位置.一般 ...

  7. python函数(2):函数进阶

    昨天说了函数的一些最基本的定义,今天我们继续研究函数.今天主要研究的是函数的命名空间.作用域.函数名的本质.闭包等等 预习: 1.写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的 ...

  8. ETL作业调度软件TASKCTL4.1单机部署

    单机部署,实际上就是将EM节点和一个Server节点安装到同一个地方.EM节点是TASKCTL服务端的最顶层,主要负责客户端与服务端之间的通信.Server节点是TASKCTL的调度服务控制层,也有A ...

  9. CentOS 7 安装Subversion, 并用Nginx代理

    环境:CentOS 7.3.1611 分三步:第一步:安装subversion第二步:安装httpd第三步:安装nginx 操作步骤: 安装subversion, 命令 -> yum -y in ...

  10. [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...