Sequence是oracle中的一个非常常用的功能,开发经常会频繁使用。但是在生产环境中经常有应用反馈通过sequence生成的自增主键会出现不连续跳号的现象,而且是几十个几十个地跳,为了弄清楚sequence跳号的原因和机制,进行了一些研究和实验。

事务回滚引起的跳号

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

SQL> create sequence test_seq

start with 1

increment by 1

Maxvalue 9999999999

Cache 30

Order;

Sequence created.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

1

SYS@orcl>insert into test_tab select test_seq.nextval from dual;

1 row created.

SYS@orcl>rollback;

Rollback complete.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

3

并发访问序列引起的跳号

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

Session 1:

SYS@orcl>begin

for i in 1..50000 loop

Insert into ta select test_seq.nextval from dual;

end loop;

end;

/

PL/SQL procedure successfully completed.

Session 2:

SYS@orcl>begin

for i in 1..50000 loop

insert into tb select test_seq.nextval from dual;

end loop;

end;

/

PL/SQL procedure successfully completed.

SYS@orcl>select * from ta where rownum<10;

ID

----------

466322

466324

466326

466327

466329

466330

466332

466333

466335

9 rows selected.

发现序号并不连续,高并发情况下存在sequence争用。

FLUSH SHARED_POOL会导致CACHE的序列跳号

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

SYS@orcl>alter sequence test_seq cache 30;

Sequence altered.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560432

SYS@orcl>alter system flush shared_pool;

System altered.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560462

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

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

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560464

SYS@orcl>select object_id from dba_objects where object_name='TEST_SEQ';

OBJECT_ID

----------

20306

SYS@orcl>select increment$,minvalue,maxvalue,highwater,cache from seq$ where obj#=20306;

INCREMENT$   MINVALUE   MAXVALUE  HIGHWATER      CACHE

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

1           1   9999999999     560492         30

SYS@orcl>shutdown abort;

ORACLE instance shut down.

SYS@orcl>startup;

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560492

而在正常关闭数据库的情况下,sequence没有发生跳号

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560526

SYS@orcl>shutdown immediate;

Database closed.

Database dismounted.

ORACLE instance shut down.

SYS@orcl>startup;

ORACLE instance started.

Total System Global Area 4375998464 bytes

Fixed Size                  2260328 bytes

Variable Size            1946157720 bytes

Database Buffers         2415919104 bytes

Redo Buffers               11661312 bytes

Database mounted.

Database opened.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560527

设置test_seq为nocache,然后异常宕机

SYS@orcl>alter sequence test_seq nocache;

Sequence altered.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560528

SYS@orcl>shutdown abort;

ORACLE instance shut down.

SYS@orcl>startup;

ORACLE instance started.

Total System Global Area 4375998464 bytes

Fixed Size                  2260328 bytes

Variable Size            1946157720 bytes

Database Buffers         2415919104 bytes

Redo Buffers               11661312 bytes

Database mounted.

Database opened.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560529

查阅资料发现数据库正常关闭的情况下,会触发一个update seq$的操作,把当前的sequence.nextval的值更新到seq$.highwater中,从而使得sequence在有cache的情况下,数据库正常关闭未出现nextval跳跃(currval也同样不跳跃);而在数据库异常关闭之时,数据库不能及时将sequence.nextval更新到eq$.highwater从而引起sequence cache中的值丢失,从而可能出现了sequence使用cache导致跳跃的情况

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

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560530

SYS@orcl>exec dbms_shared_pool.keep('test_seq','q');

PL/SQL procedure successfully completed.

SYS@orcl>alter system flush shared_pool;

System altered.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560531

SYS@orcl>alter sequence test_seq cache 30;

Sequence altered.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560532

SYS@orcl>shutdown abort

ORACLE instance shut down.

SYS@orcl>startup;

ORACLE instance started.

Total System Global Area 4375998464 bytes

Fixed Size                  2260328 bytes

Variable Size            1946157720 bytes

Database Buffers         2415919104 bytes

Redo Buffers               11661312 bytes

Database mounted.

Database opened.

SYS@orcl>select test_seq.nextval from dual;

NEXTVAL

----------

560562

其实如果业务允许,单号出现跳号也无所谓的情形最好,如果碰到业务要求绝对不能出现单号出现跳号的情况,那么就不能使用序列号了。

RAC环境中的sequence

如果是cache下的order,单实例下没有影响,而rac下多实例缓存相同的sequence,如果order的取大量sequence则会出现短暂的资源竞争(由于资源需要在多实例间传递),性能要比noorder差很多。尤其注意nocache order的sequence,即对于sequence大量争用,还需要在实例间传递竞争资源,严重的甚至导致系统直接hang住,对于rac的环境需要通过cache fusion和序列的机制认真分析来找到性能瓶颈的根本原因。

oracle为了在rac环境下为了sequence的一致性,使用了三种锁:row cache lock、SQ锁、SV锁。row cache lock的目的是在sequence指定nocache的情况下调用sequence.nextval过程中保证序列的顺序性;SQ锁是应用于指定了cache+noorder的情况下调用sequence.nextval过程中。SV 锁(dfs lock handel) 是调用sequence.nextval期间拥有的锁。前提是创建sequence时指定了cache 和order属性 (cache+order)。order参数的目的是为了在RAC上节点之间生成sequence的顺序得到保障。

创建sequence赋予的cache值较小时,有enq:sq-contention等待增加的趋势。cache的缺省值是20.因此创建并发访问多的sequence时,cacheh值应取大一些。否则会发生enq:sq-contention等待事件。

rac上创建sequence时,如果指定了cache大小而赋予noorder属性,则各节点将会把不同范围的sequence值cache到内 存上。若两个节点之间都必须通过依次递增方式使用sequence,必须赋予如下的order属性(一般不需要这样做)”sql> create sequence seq_b cache 100 order”。如果是已赋予了cache+order属性的sequence,oracle使用SV锁进行同步。SV锁争用问题发生时的解决方法与sq锁 的情况相同,就是将cache 值进行适当调整。

在RAC多节点环境下,Sequence的Cache属性对性能的影响很大。应该尽量赋予cache+noorder属性,并要给予足够的 cache值。如果需要保障顺序,必须赋予cache+order属性。但这时为了保障顺序,实例之间需要不断的交换数据。因此性能稍差。

oracle获取序列跳号,Oracle sequence跳号知多少相关推荐

  1. oracle获取序列并赋值,Oracle中序列的使用

    数据库设计的三大范式第一条就是独立的表结构中必须有唯一主键来标识表中数据.在以往微软的SQL Server(duo版本)平台上.手动编码实现表中主键.并设定为自增列是极其简单.编码如下: typeid ...

  2. oracle 获取系统年 月,Oracle 获取当前年、月、日

    Oracle 获取当前年.月.日 第一种:new Timestamp(System.currentTimeMillis()): 第二种:sysdate; 1.//oracle中extract()函数从 ...

  3. oracle 修改序列 next number,oracle序列详解

    }] //最大值 [{MINVALUE n | NOMINVALUE}] //最小值 [{CYCLE | NOCYCLE}] //循环/不循环 [{CACHE n | NOCACHE}];//分配并存 ...

  4. oracle字段序列自增长,ORACLE序列(字段自增长)

    序列:是oacle提供的用于产生一系列唯一数字的数据库对象. Ø 自动提供唯一的数值 Ø 共享对象 Ø 主要用于提供主键值 Ø 将序列值装入内存可以提高访问效率 创建序列: 1.  要有创建序列的权限 ...

  5. oracle+创建序列自增,oracle序列详解和建立自增主键

    序列: 是oacle提供的用于产生一系列惟一数字的数据库对象.sql l 自动提供惟一的数值数据库 l 共享对象性能 l 主要用于提供主键值测试 l 将序列值装入内存能够提升访问效率spa 1.首先建 ...

  6. oracle 用序列插入表,Oracle序列的使用与说明

    1.序列的创建与说明 创建序列,Oracle序列的语法格式为:CREATE SEQUENCE 序列名[INCREMENT BY n][START WITH n][{MAXVALUE/ MI 1.序列的 ...

  7. oracle查看序列数据语法,oracle查询各种数据字典的语法

    ORACLE的数据字典是数据库的重要组成部分之一,它随着数据库的产生而产生, 随着数据库的变化而变化,体现为sys用户下的一些表和视图.数据字典名称是大写的英文字符. 数据字典里存有用户信息.用户的权 ...

  8. oracle获取减一年,oracle日期减一年 oracle指定日期减一天

    oracle怎么将当前时间减一年? 1. 打开PLSQL,连接Oracle数据库,用SQL语句创建测试表.这里只做了演示,所以不创建主键和索引.; 2. 使用SQL语句将3行测试数据插入到上一步创建的 ...

  9. oracle获取上年年初,【Oracle】TRUNC:获取去年年初和年末,获取月初和月末;

    一.需求 当前时间:2018-1-6 16:56:01 因为要在数据库里获取去年年初,即(2017-1-1 00:00:00)和去年年末(2017-12-31 23:59:00)这两个时间段内的数据: ...

最新文章

  1. GEO芯片数据探针id转化
  2. 批量 ping 测试脚本(IP 扫描)
  3. html设置团偏跟着移动,雷阵雨云团向东偏南移动,北京两地将有强降雨+7级大风+冰雹!...
  4. 技术人的少年感,和年龄无关。
  5. 营业税计提及企业所得税的相关计算公式
  6. nginx linux下载文件,linux – 从nginx缓慢下载大型静态文件
  7. SPOJ DQUERY D-query(主席树 区间不同数个数)
  8. 【回文串7】LeetCode 234. Palindrome Linked List
  9. 数据库oracle有哪些函数,Oracle函数大全
  10. Caffe学习:Forward and Backward
  11. JAVA SSO单点登录原理以及实现方案
  12. 数据拟合MATLAB与origin哪个好,Origin:数据处理、作图和拟合的利器
  13. 内网渗透学习-Windows信息收集
  14. Spring Boot 2.0 配置图文教程
  15. 微软 Azure人工智能认知服务打造语音提醒喝水助手(带源码和演示地址)
  16. 408计算机学科专业基础综合——操作系统
  17. 迈动互联中标中建集团
  18. 基于混合密码体制的端到端短信通讯系统(Java实现+AES+RSA+json)
  19. 工程热力学Ch.4 热二律
  20. win10如何打开摄像头_win10中如何打开画图工具--win10专业版

热门文章

  1. 向seaborn传递matplotlib绘图参数,精细地控制seaborn输出图形
  2. SAP Spartacus SpartacusB2cConfigurationModule 的使用场景
  3. 如何使用 SAP API Portal Policy Editor 给 SAP API 调用自动添加认证信息
  4. SAP AMDP介绍 - ABAP托管的HANA数据库过程
  5. SAP UI5 busy Dialog debug - 单步调试
  6. SAP Fiori INTEROP tile cache
  7. SAP ABAP gateway调用后台系统时选择RFC的决定逻辑
  8. 步骤2 - websocket服务器转发请求给orchestra
  9. include element into ABAP word document
  10. 研究partner determination的逻辑能否抽出来,以API的形式被我们Odata service implementation code里调用?