Oracle的sequence自增的注意事项

5250阅读 0评论2014-07-03 hiyachen
分类:Oracle

在数据库中自增是一个让人又爱又怨的功能。虽然Oracle、sqlserver、mysql都提供了自己的方法。但各个DB也都明确要求在一定的条件下,要用法正确。
下面介绍一下:Oracle的sequence自增中的问题及解决。
现象:
用 sequence 生成主键,cache 值设为20 。发现了一个异常,那就是生成的主键不连续,比如说上个数字是4551552,下个就成了4552838 ,差别实在是太大了。
我的代码里(java 工程,ibatis insert语句)调用该 sequence.nextval
只有一处啊,没有其他地方调用 nextval 。

解决:

可以确定是merge into 语句的问题了,在ibatis 配置文件中如下这么写是有问题的:

                       merge into tablename using
                         (select count(*) count from tablename where condition1) numcount
                       on (numcount.count <> 0)
                       when matched then
                         UPDATE SET A=A+1 WHERE  condition2
                       when not matched then
                         INSERT (ID,A,B,C,D)
                         VALUES(tablename_SEQUENCE.NEXTVAL,  #a#,  #b#,  #c#,  #d#  )
         ]]>
 

正确的写法是这样:

       
                
       

                       merge into tablename using
                         (select count(*) count from tablename where condition1) numcount
                       on (numcount.count <> 0)
                       when matched then
                         UPDATE SET A=A+1 WHERE  condition2
                       when not matched then
                         INSERT (ID,A,B,C,D)
                         VALUES(tableid,  #a#,  #b#,  #c#,  #d#  )
         ]]>
 

分析:
   http://hiyachen.blog.chinaunix.net
1:merge into tablename using (select count(*) count from tablename where condition1) numcount
      on (numcount.count <> 0)
之前也遇到过,序列值涨到 好几十亿 。这个条件的写法,满足update时,相当于全表都符合,会生成全表的序列。
危险举例:当tablename 达到几十万行记录以后, 可以把数据库搞挂了,CPU飙高

2:sequence的读取不是采用i++这种的形式,
1)系统会读取例如sequence:1-100到内存中去,用于insert操作,当用到50时候,电脑奔溃了。这个时候电脑重启后再进行insert插入则会读取101-200,而不是从51开始。
2)在进行insert操作时候,使用的是sequence:150,你突然rollback一次,那么下次使用的sequence是:151,这个时候150就被浪费了。

上一篇:HTTP基础:ServletContext和Servletcontextlistener的作用
下一篇:apache、nginx、epoll等的应用