`

(转)关于oracle的sequence

阅读更多
http://web4.blog.163.com/blog/static/189694131201132184850561/

今天碰到一个问题,数据库表有一个字段的值是通过sequence来生成的,但是,获取到的数值却并不连续,而且是非常有规律的一下子就跳跃到21,刚开始是怀疑代码的问题,但是代码当中根本就没有操作这个sequence,写代码的人甚至连这个sequence的名字都不知道。然后,就发现, sequence有一个属性是cache size,它的值是20,莫非跟这个有关系?果然如此!
参考:http://blogold.chinaunix.net/u/30637/showart_1277599.html
SEQUENCE — cache 的用处 
在创建序列的语法中,有一个子句为 cache,它的用处是缓存指定个数的序列值。比如你设置的 cache 是20,那么在获取 nextval 时,Oracle 会直接从 cache 中取下一个序列值,如果 cache 中缓存的序列值没有了(比如 cache 中的序列值用完了,或者被手工清空了),那么 Oracle 会再次产生20个序列值,并放置 cache 中供使用,这样有助于提高序列值的获取速度。

下面我们做个测试:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL> create sequence SEQ_TEST1
  2  minvalue 1
  3  maxvalue 1000
  4  start with 1
  5  increment by 1
  6  cache 20
  7  order;
序列已创建。
-- 刚刚创建的序列必须先用 nextval 来获取一个初始值
SQL> select SEQ_TEST1.currval from dual;
select SEQ_TEST1.currval from dual
       *
ERROR 位于第 1 行:
ORA-08002: 序列 SEQ_TEST1.CURRVAL 尚未在此会话中定义
SQL> select SEQ_TEST1.nextval from dual;
   NEXTVAL
----------
         1
SQL> select SEQ_TEST1.currval from dual;
   CURRVAL
----------
         1
-- 清空 cache 中缓存的序列值
SQL> alter system flush shared_pool;
系统已更改。
-- 查询当前值,没有变化,仍是1
SQL> select SEQ_TEST1.currval from dual;
   CURRVAL
----------
         1
-- 查询下一个值:Oracle 发现 cache 中的序列值没有了,会再次产生20个序列值供使用。
-- 所以这里得到的结果不是2,而是21。
SQL> select SEQ_TEST1.nextval from dual;
   NEXTVAL
----------
        21
-- 再试一次
SQL> alter system flush shared_pool;
系统已更改。
SQL> select SEQ_TEST1.currval from dual;
   CURRVAL
----------
        21
SQL> select SEQ_TEST1.nextval from dual;
   NEXTVAL
----------
        41
-- 问题:Oracle 下一次取的20个值是从哪里开始计算的呢,是 currval + 20,
-- 还是每个 cache + 20 呢?我们试验一下。
SQL> select SEQ_TEST1.nextval from dual;
   NEXTVAL
----------
        42
-- 现在序列的当前值是42。如果是用 currval + 20 来计算,那么清空 cache 后,
-- 获得的 nextval 应该是62;如果是 cache + 20,那应该是 61。
-- 看看实验结果吧:
SQL> alter system flush shared_pool;
系统已更改。
SQL> select SEQ_TEST1.currval from dual;
   CURRVAL
----------
        42
SQL> select SEQ_TEST1.nextval from dual;
   NEXTVAL
----------
        61
结论:cache 可以用来提高序列值的获取速度,但有可能会浪费一些序列号,应该根据实际情况来设置 cache 的大小。
也就是说,oracle会把sequence缓存到shared pool里面,如果数据库down掉了,下次再启动的时候就会出现gap。

但是,我们的数据库并没有down掉啊,一直都在正常运行呢!
参考:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:369390500346406705
在这里面tom大师说了,sequence的唯一的用处是保证数值的唯一性,既不保证gap free,也不保证order。
you cannot expect a sequence to return gap free values. a sequence has one purpose: assign unique numbers to stuff. Nothing else. there will be gaps, gaps are normal, expected, good, ok, fine. they will be there, there is no avoiding them. This is not a problem, it is expected, it is not "fixable" - a "rollback" for example will generate a gap if some session selected a sequence.
Do not assume they are gap free and all is well in the world.

还说,不用担心sequence会用完,
set cache to 10000 - but don't lower it.
you'll never run out of values. even if you lose 10,000 per second
  1* select 999999999999999999999999999/10000/60/60/24/365 from dual
ops$tkyte%ORA9IR2> /
999999999999999999999999999/10000/60/60/24/365
----------------------------------------------
                                    3.1710E+15
that is how many years you would have before running out of values

什么时候会出现gap呢?
(1)事务回滚会导致gap
(2)数据库down掉会导致gap
(3)just normal aging of things out of the SGA can cause it.内存用完了也会导致gap的出现。原来我们的问题在这里。我们就是在产生下一个序列号之前使用了一个非常消耗内存的工具,导致oracle缓存的sequence被替换出内存。

但是,tom大师同时也说了,千万不要设置nocache,alter sequence XXX nocache;
do not use nocache - that would be like setting "slow=true" in your init.ora parameter file.
http://blog.csdn.net/tianlesoftware/archive/2010/11/08/5995051.aspx
这篇文章有启用和禁用cache在性能方面的数值比较。

如果我们想不出现gap该如何做呢?
那肯定就不能使用sequence了。
CACHE or NOCACHE, if your requirement is truly to make sure there are no gaps, then a sequence is the wrong solution. You may get fewer gaps with NOCACHE, so they may be less noticeable, but you have accepted the possibility of gaps for a requirement that 'demands' no gaps. If you want to use a sequence, you must first negotiate that 'gap-free' requirement away, and make sure none of the design depends on the keys being 'gap-free'. If the requirement sticks, then you have to use some other mechanism - maybe a table of available keys, or something else. Also make sure there is no requirement that they are assigned in order, and no design dependency anywhere that they be assigned in order. Use a timestamp to keep track of 'in what order were these done'; if that's not enough, then you need more thought and more work.
有人说:每次从表里面查询出最大的,然后加1,作为下一条记录的id,但是,如果最大的记录被删掉以后,下一次再插入的记录的id和被删掉的id是一样的,这样的数据会引发混乱。
还有人说,另外定义一个专门存放最大id的表,就两列,表名和当前最大的id,然后需要往表里面插入的时候,select for update,得到下一个id,这就保证id一直往上增加。
这两种方式都得注意,必须要序列化操作,防止多线程导致id重复。
分享到:
评论
1 楼 shenfuli 2013-08-13  
今天我也遇到了

相关推荐

    Oracle sequence 重置(失效恢复)

    ### Oracle Sequence 重置(失效恢复) 在进行Oracle数据库移植或维护时,可能会遇到Sequence失效的问题。这种情况通常发生在数据迁移后,原有的Sequence不再与表中的最大值相匹配,导致新记录插入时出现ID冲突或者...

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

    Oracle 创建自增字段方法-ORACLE SEQUENCE 的简单介绍 Oracle SEQUENCE 是一种特殊的数据库对象,用于生成一系列唯一的数值,通常用于主键或其他需要唯一标识的字段。下面将详细介绍 Oracle 创建自增字段方法-...

    ORACLE SEQUENCE的简单介绍

    ### ORACLE SEQUENCE 的详细介绍与应用 #### 一、概述 在数据库开发和管理中,自动编号是一...以上是关于 Oracle Sequence 的详细介绍及应用场景,希望能帮助开发者更好地理解和使用 Oracle 数据库中的这一强大工具。

    oracle中sequence介绍及应用

    ### Oracle中的Sequence介绍及应用 #### 一、Sequence概述 在Oracle数据库中,Sequence是一种用于自动产生数值序列的对象。它可以生成连续的整数或者非连续的整数序列,并且可以根据需求进行递增或递减。Sequence...

    oracle中的sequence实现主键增长

    Oracle中的Sequence是数据库管理系统提供的一种机制,用于生成序列化的整数,通常用于主键或唯一标识符,确保数据的唯一性和有序性。在Oracle中,Sequence不同于其他数据库系统的自增字段,例如SQL Server中的`...

    让CoolSQL支持Oracle Sequence的GeneratedKey,懂的入

    本篇文章将围绕"让CoolSQL支持Oracle Sequence的GeneratedKey"这一主题展开,探讨如何在开发过程中利用Oracle的Sequence特性并将其与CoolSQL工具相结合,以实现更高效的数据操作。 首先,Oracle Sequence是一种用于...

    分享ORACLE SEQUENCE跳号总结

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

    oracle GoldenGate 同步oracle sequence的步骤

    ### Oracle GoldenGate 同步 Oracle Sequence 的步骤 Oracle GoldenGate 是一款强大的数据复制软件,能够实现跨平台的数据复制。在企业级应用环境中,为了确保数据的一致性和完整性,经常需要将源数据库中的序列...

    使用JDeveloper开发WEB应用时同时使用Oracle的sequence和trigger

    本篇将重点介绍如何在使用JDeveloper这款强大的集成开发环境(IDE)时,结合Oracle的sequence和trigger来实现高效的数据操作。 首先,让我们理解一下sequence和trigger的概念。在Oracle中,sequence是一种自动递增...

    Hibernate Oracle sequence的使用技巧

     1、在Oracle sequence首先创建sequence  create sequence seq_idminvalue 1start with 1increment by 1cache 20;  2、在你的hbm.xml中的配置  seq_id  这样再插入数据的时候,Hibernate会自动生成如下语句: ...

    oracle 主键自增 sequence

    ### Oracle 主键自增 Sequence 的实现与应用 #### 一、Sequence 的概念及用途 在 Oracle 数据库中,`Sequence` 是一种用于生成一系列唯一数值的对象。这些数值可以按照特定的规则递增或递减,并且可以设定是否循环...

    浅谈MyBatis-Plus学习之Oracle的主键Sequence设置的方法

    在Oracle数据库中,由于不支持自动递增的主键策略,开发者通常会使用Sequence来生成主键值。本文将深入探讨如何在MyBatis-Plus(MP)框架中配置Oracle的主键Sequence。 首先,Oracle Sequence是Oracle数据库提供的...

    Oracle Sql语句转换成Mysql Sql语句

    6. **序列**:Oracle使用序列(SEQUENCE)来生成唯一ID,MySQL则常使用自增(AUTO_INCREMENT)字段。 7. **视图和存储过程**:Oracle的视图和存储过程可能需要在MySQL中重新编写,因为两者的语法和权限管理不同。 ...

    sequence-generator:比oracle sequence更加强大的序列生成器,支持分布式环境,配合MHA可完美做到高可用,与spring无缝集成,使用非常简单可靠

    sequence-generator简介类似于oracle的sequence,但更加强大支持分布式环境下sequence的生成使用乐观锁和AtomicLong确保sequence的唯一性使用及其简单db scriptCREATE TABLE sequence_database.sequence ( name ...

    详解ORACLE SEQUENCE用法

    在oracle中sequence就是序号,每次取的时候它会自动增加。sequence与表没有关系。 1、Create Sequence 首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限。 创建语句如下: CREATE SEQUENCE seqTest INCREMENT...

    oracle 存储过程使用 sequence

    在提供的压缩包文件`07_调整级别示例过程(业务库_p_scegetuserinfor).orasql`中,可能包含了关于如何在实际业务场景下调整Sequence或使用Sequence的示例过程。这个过程可能涉及到更复杂的业务逻辑,比如根据不同的...

    oracle_sequence.rar_oracle

    在Oracle中,序列(Sequence)是一个非常重要的概念,它主要用于生成唯一的整数序列,常常被用来作为主键值,特别是在插入新记录时自动增加。在本篇文章中,我们将深入探讨Oracle序列的创建、使用以及其在实际应用中...

Global site tag (gtag.js) - Google Analytics