- 浏览: 7866313 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (2425)
- 软件工程 (75)
- JAVA相关 (662)
- ajax/web相关 (351)
- 数据库相关/oracle (218)
- PHP (147)
- UNIX/LINUX/FREEBSD/solaris (118)
- 音乐探讨 (1)
- 闲话 (11)
- 网络安全等 (21)
- .NET (153)
- ROR和GOG (10)
- [网站分类]4.其他技术区 (181)
- 算法等 (7)
- [随笔分类]SOA (8)
- 收藏区 (71)
- 金融证券 (4)
- [网站分类]5.企业信息化 (3)
- c&c++学习 (1)
- 读书区 (11)
- 其它 (10)
- 收藏夹 (1)
- 设计模式 (1)
- FLEX (14)
- Android (98)
- 软件工程心理学系列 (4)
- HTML5 (6)
- C/C++ (0)
- 数据结构 (0)
- 书评 (3)
- python (17)
- NOSQL (10)
- MYSQL (85)
- java之各类测试 (18)
- nodejs (1)
- JAVA (1)
- neo4j (3)
- VUE (4)
- docker相关 (1)
最新评论
-
xiaobadi:
jacky~~~~~~~~~
推荐两个不错的mybatis GUI生成工具 -
masuweng:
(转)JAVA获得机器码的实现 -
albert0707:
有些扩展名为null
java 7中可以判断文件的contenttype了 -
albert0707:
非常感谢!!!!!!!!!
java 7中可以判断文件的contenttype了 -
zhangle:
https://zhuban.me竹板共享 - 高效便捷的文档 ...
一个不错的网络白板工具
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重复。
今天碰到一个问题,数据库表有一个字段的值是通过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重复。
发表评论
-
mybatis generator中的字段大小写生成问题
2017-10-22 19:35 11266mybatis generator插件中,如果 mysql数据 ... -
MySQL统计一个列中不同值的数量
2017-07-11 14:04 16242https://yiqiwuliao.com/post/mys ... -
mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
2017-03-02 09:44 1745权限问题,授权 给 root 所有sql 权限 mysql ... -
几个不错的MYSQL 优化TIPS
2016-11-19 12:30 780图片来自http://imysql.com/的PDF分享 [ ... -
powerdesign 逆向ORACLE的坑
2016-09-27 17:08 533要注意的是,在WIN 64中,如果要用powerdesin 来 ... -
( 转)mysql中删除两条重复记录中的一条
2015-10-19 20:19 1304| id | createTime | labId | pub ... -
mysql中sql语句=,>的时候的索引设置
2015-05-02 12:27 1292在 https://www.percona.com/blog/ ... -
mysql中profile的使用
2015-04-30 11:11 2197mysql 的 sql 性能分析器主要用途是显示 sql 执行 ... -
mysql中的sql mode
2015-04-13 11:29 1125mysql sql mode小结 1 sql mode可以 ... -
PROCEDURE ANALYSE()为mysql提高性能提供建议
2015-04-02 16:37 1421procedure analyse();语法如下 select ... -
mongodb中意外退出的问题
2015-02-11 14:32 1319mongodb启动的时候,意外退出: Unclean shut ... -
mysql 5.5中保留字查询
2014-06-05 23:16 1460mysql 5.5中保留字查询 http://www.5is ... -
(转)oracle 临时表空间的增删改查
2014-03-18 12:44 1106oracle 临时表空间的增删改查 1、查看临时表空间 (d ... -
pl-sql developer安装
2014-02-07 09:16 1103一直都是机器本机上有oracle,所以装pl sql deve ... -
oracle中的nvl,nvl2等参数
2013-12-26 11:18 22511.nul函数将一个null值转换为一个实际的值。 数据类型可 ... -
Oracle中的ROWNUM rowid 以及MySQL中实现rownum功能类似的语句
2013-12-26 11:08 2336http://gong-10140.iteye.com/blo ... -
ORACLE XE版本的限制
2013-12-07 08:11 361810g中用户数据最大为4G, 11G中最大为11G,如果超出大 ... -
oracle中监控索引是否可用
2013-11-04 07:22 1048在oracle中,可以使用如下的方法监控索引是否可用: a ... -
mysql 5.6中的时间类型的新精度介绍
2013-10-28 09:33 8381留意到mysql 5.6中,可以使用select now(6) ... -
<<oracle索引技术》读书笔记1
2013-08-25 16:23 1300expert indexing in oracle datab ...
相关推荐
在Oracle数据库移植过程中,sequence可能失效,本资源可使失效的sequence重新恢复作用
Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍 很有用哦
oracle中sequence介绍及应用
oracle GoldenGate 同步oracle sequence的步骤
教你如何使用oracle中的sequence,实现主键自动增长
在ORACLE数据库中,序列(SEQUENCE)是使用非常频繁的一个数据库对象,但是有时候会遇到序列(SEQUECNE)跳号(skip sequence numbers)的情形,那么在哪些情形下会遇到跳号呢? 事务回滚引起的跳号 不管序列有...
Sql Server 数据库,插入操作时可以设置,自动编号。但是ORACLE 数据库,具有里一个东西SEQUENCE,在这儿介绍
1、在Oracle sequence首先创建sequence create sequence seq_idminvalue 1start with 1increment by 1cache 20; 2、在你的hbm.xml中的配置 seq_id 这样再插入数据的时候,Hibernate会自动生成如下语句: ...
Oracle自增长主键自动生成类 public static int nextID String table { if table null return 1; table table toLowerCase ; String strKey table; if sequences containsKey strKey { ...
oracle 主键自增 给你个例子吧:看看肯定明白了!!! 首先,你要有一张表! CREATE TABLE example( ID Number(4) NOT NULL PRIMARY KEY, NAME VARCHAR(25), PHONE VARCHAR(10), ADDRESS VARCHAR(50) ); ...
在oracle中sequence就是序号,每次取的时候它会自动增加。sequence与表没有关系。 1、Create Sequence 首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE权限。 创建语句如下: CREATE SEQUENCE seqTest INCREMENT...
NULL 博文链接:https://snowelf.iteye.com/blog/575555
在开发过程中,可能会用到oracle sequence语句,本文以oracle sequence语句如何重置进行介绍,需要的朋友可以参考下Oracle重置sequence语句1 Sql代码 代码如下: DECLARE n NUMBER(10 ); tsql VARCHAR2(100 ); p_...
sequence-generator简介类似于oracle的sequence,但更加强大支持分布式环境下sequence的生成使用乐观锁和AtomicLong确保sequence的唯一性使用及其简单db scriptCREATE TABLE sequence_database.sequence ( name ...
oracle自动增长列。 自动序列化, SEQUENCE。
主要介绍了浅谈MyBatis-Plus学习之Oracle的主键Sequence设置的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
NULL 博文链接:https://charles-xu-ebaotech-com.iteye.com/blog/721902