前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Oracle sequence跳号知多少

Oracle sequence跳号知多少

作者头像
数据库架构之美
修改2019-12-27 19:55:42
2.1K0
修改2019-12-27 19:55:42
举报
文章被收录于专栏:数据库架构之美

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属性。但这时为了保障顺序,实例之间需要不断的交换数据。因此性能稍差。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • RAC环境中的sequence
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档