ORACLE SEQUENCE跳号总结
在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跳号总结的更多相关文章
- 从SEQUENCE跳号说起
http://blog.csdn.net/agaric717/article/details/6690890 一个应用上线后发现一个使用SEQUENCE值来生成的主键经常出现断号,而且断号不是一两个, ...
- SQL Server解惑——标识列的限制和跳号现象
1:每个表只能创建一个标识列. 如下测试所示,如果表中有一个标识列,新增一个标识列就会遇到错误"Multiple identity columns specified for table ...
- oracle SEQUENCE 创建, 修改,删除
oracle创建序列化: CREATE SEQUENCE seq_itv_collection INCREMENT BY 1 -- 每次加几个 STA ...
- ORACLE SEQUENCE用法
引用自: http://www.cnblogs.com/hyzhou/archive/2012/04/12/2444158.html 在oracle中sequence就是序号,每次取的时候它会自动增加 ...
- Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍
引用自 :http://www.2cto.com/database/201307/224836.html Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍 先假设有这么一个表 ...
- 【转】oracle Sequence
http://blog.csdn.net/zhoufoxcn/article/details/1762351 在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没 ...
- ORACLE SEQUENCE 介绍
在oracle中sequence就是所谓的序列号,每次取的时候它会自己主动添加,一般用在须要按序列号排序的地方. 1.Create Sequence 你首先要有CREATE SEQUENCE或者C ...
- ORACLE SEQUENCE用法 (自增长)
在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没有关系. 1.Create Sequence 首先要有CREATE SEQUENCE或者CREATE ...
- ORACLE SEQUENCE的简单介绍
先假设有这么一个表: create table S_Depart ( DepartId INT not null, DepartName NVARCHAR2() not null, DepartOrd ...
随机推荐
- UDP和多线程服务器
UDP: UDP是数据报文传输协议,这个传输协议比较野蛮,发送端不需要理会接收端是否存在,直接就发送数据,不会像TCP协议一样建立连接.如果接收端不存在的话,发送的数据就会丢失,UDP协议不会去理会数 ...
- [转]从入门到精通: 最小费用流的“zkw算法”
>>>> 原文地址:最小费用流的“zkw算法” <<<< 1. 网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本 ...
- Java 多态的实现原理
一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 .编译时多态(又称静态多态) .运行时 ...
- spring加载异常
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' ...
- Actor模型原理
1.Actor模型 在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用 ...
- 决策树(ID3 )原理及实现
1.决策树原理 1.1.定义 分类决策树模型是一种描述对实例进行分类的树形结构.决策树由结点和有向边组成.结点有两种类型:内部节点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类. 举一个通俗的 ...
- Nginx安装部署与测试
场景:项目需要部署在生产环境中,这些新的工具都需要在生产环境中去实践练习.有时间再部署一套ELK的日志分析系统,这样的系统才算具有一定的应用价值. 1 Nginx安装 用root用户安装,采用源代码编 ...
- 配置LAMP实现WordPress
环境说明: 在同一台主机上实现LAMP(Linux + Apache + MariaDB + PHP) CentOS 7.3.Apache 2.4.6.MariaDB 5.5.52.PHP 5.4.1 ...
- nopCommerce 3.9 大波浪系列 之 开发支持多店的插件
一.基础介绍 nop支持多店及多语言,本篇结合NivoSlider插件介绍下如何开发支持多商城的小部件. 主要接口如下: ISettingService 接口:设置接口,可实现多店配置. (点击接口介 ...
- Swift 细节
1.swift ?和 !的区别 1.1 Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化.如果在使 ...