oracle的sequence出现gap的问题
转自 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重复。
oracle的sequence出现gap的问题的更多相关文章
- JDBC读取新插入Oracle数据库Sequence值的5种方法
Oracle的sequence实现非常灵活,所以也带来一些易用性问题,如何取到新插入记录生成的sequence值与其它数据库有较大差别,本文详国介绍了5种实现读取新插入记录sequence值的方法. ...
- Hibernate用Oracle的sequence生成自增Id
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBL ...
- Oracle Metric sequence load elapsed time
Oracle Metric sequence load elapsed time The sequence load elapsed time Oracle metric is the amount ...
- oracle中sequence(自增序号)的用法
转载:https://www.cnblogs.com/liuzy2014/p/5794928.html 在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没有关系 ...
- oracle创建sequence序列语法
在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没有关系 1.create sequence create sequence SEQ_LOG_ID minval ...
- oracle关于sequence的个人理解
oracle关于sequence的个人理解 1. sequence在多用户使用时的同步问题 个人感觉sequence是以连接(会话)为基础,类似于java中使用mysql的一个connection 网 ...
- Oracle序列(Sequence)创建、使用、修改、删除
Oracle对象课程:序列(Sequence)创建.使用.修改.删除,序列(Sequence)是用来生成连续的整数数据的对象.序列常常用来作为主键中增长列,序列中的可以升序生成,也可以降序生成.创建序 ...
- oracle之sequence详解
Oracle提供了sequence对象,由系统提供自增长的序列号,每次取的时候它会自动增加,通常用于生成数据库数据记录的自增长主键或序号的地方. sequence的创建需要用户具有create seq ...
- Oracle中sequence的使用方法
在Oracle数据库中,sequence等同于序列号,每次取的时候sequence会自动增加,一般会作用于需要按序列号排序的地方. 1.Create Sequence (注释:你需要有CREATE S ...
随机推荐
- R程序包
=== 数据基础操作 ===reshape2 横向.纵向做数据变换,例如把纵向堆叠在数据库中的证券行情数据转换成一个按照不同证券代码横向排列,按照时间纵向排列收盘价的数据表stringr 方便地用正则 ...
- CSSREM
一个CSS的px值转rem值的Sublime Text 3自动完成插件. 安装 下载本项目,比如:git clone https://github.com/flashlizi/cssrem 进入pac ...
- Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.
我是 win7 64位 解决办法: 1, win+r 快捷键打开 “运行”,输入regedit 打开注册表 2,找到 HKEY_CLASSES_ROOT\CLSID\{00020420-0000-00 ...
- Vuejs 整合 MUi
整合方法和使用axios的方法类似.具体步骤如下: 引入mui的css和js import mui from './lib/mui/js/mui.js' import './lib/mui/css/m ...
- Android 开发工具类 16_NotificationActivity
在前台运行的 Activity 可以通过Dialog.Toast 向用户发出提示信息,而后台运行的程序,如下载.收到信息等 Service 应用,则需要使用 Notification(通知)向用户发出 ...
- tensorflow VocabularyProcessor
from tensorflow.contrib import learn import numpy as np vocab_process = learn.preprocessing.Vocabula ...
- EventLog组件读写事件日志
使用.Net中的EventLog控件使您可以访问或自定义Windows 事件日志,事件日志记录关于重要的软件或硬件事件的信息.通过 EventLog,可以读取现有日志,向日志中写入项,创建或删除事件源 ...
- 532 -数组中的K-diff对
例1: 输入: [3,1,4,1,5],k = 2 输出: 2 说明:阵列中有两个2-diff对,(1,3)和(3,5). 虽然我们在输入中有两个1,但我们应该只返回唯一对的数量. 例2: 输入: ...
- 哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)
前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Metho ...
- properties配置文件编码问题
properties配置文件编码问题 person.last-name=哈哈 person.age=18 person.bitrh=2019/01/12 person.boss=false perso ...