首页 > Oracle > Oracle序列号简述
2016
03-22

Oracle序列号简述

序列号SEQUENCE:是Oracle提供的用于产生一系列唯一数字的数据库对象。

 

序列号在数据库中是一个共享对象, 序列号是一个计数器,它并不会与特定的表关联。

主要用于提供主键值或唯一约束值。

将序列值装入内存可以提高访问效率。

 

创建序列号语法:

CREATE SEQUENCE [SCHEMA.]SEQUENCE_NAME

[INCREMENT BY N]

[START WITH N]

[{MAXVALUE N | NOMAXVALUE}]

[{MINVALUE N | NOMINVALUE}]

[{CYCLE | NOCYCLE}]

[{CACHE N | NOCACHE}];

 

SEQUENCE_NAME:序列号名称

INCREMENT BY用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表Oracle序列的值是按照此步长递减的。

START WITH 定义序列的初始值(即产生的第一个值),默认为1。

MAXVALUE 定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项,代表没有最大值定义,这时对于递增Oracle序列,系统能够产生的最大值是10的27次方;对于递减序列,最大值是-1。

MINVALUE定义序列生成器能产生的最小值。选项NOMAXVALUE是默认选项,代表没有最小值定义,这时对于递减序列,系统能够产生的最小值是-10的26次方;对于递增序列,最小值是1。

CYCLE和NOCYCLE 表示当序列生成器的值达到限制值后是否循环。CYCLE代表循环,NOCYCLE代表不循环。如果循环,则当递增序列达到最大值时,循环到最小值;最小值为1。对于递减序列达到最小值时,循环到最大值。如果不循环,达到限制值后,继续产生新值就会发生错误。

CACHE(缓冲)定义存放序列的内存块的大小,默认为20。NOCACHE表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能。 缓存选项会造成数据丢失,当实例异常关闭时。

 

如果指定CACHE值,ORACLE就可以预先在内存里面放置一些SEQUENCE,这样存取的快些。CACHE里面的取完后,ORACLE自动再取一组到CACHE。使用CACHE或许会跳号, 比如数据库突然不正常DOWN掉(SHUTDOWN ABORT),CACHE中的SEQUENCE就会丢失。举个例子:比如你的SEQUENCE中CACHE 100,那当你SEQUENCE取到90时突然断电,那么在你重启数据库后,SEQUENCE的值将从101开始。

 

如果指定NOCACHE值,ORACLE就不会预先在内存里面存放SEQUENCE,当然这也就可以避免数据库不正常DOWN掉的SEQUENCE丢失。不过会产生一些问题:创建NOCACHE SEQUENCE在高并发访问时,容易导致ROW CACHE LOCK等待事件,主要原因是每次获取NEXTVAL时都需要修改ROWCACHE中的字典信息。使用NOCACHE SEQUENCE,还会导致如下问题:

由于每次修改字典信息都需要COMMIT,可能导致LOG FILE SYNC等待,NOCACHE SEQUENCE在RAC环境下,会对基于SEQUENCE生成的列创建的索引,造成实例间大量索引块争用,基于以上问题,避免创建NOCACHE SEQUENCE。

 

SEQUENCE相关保护机制:

ROW CACHE LOCK:在调用SEQUENCE.NEXTVAL情况下需要修改数据字典时发生,对应ROW CACHE LOCK事件。

SQ LOCK:在内存缓存(并非ROW CACHE)上获取SEQUENCE.NEXTVAL时发生,对应ENQ:SQ-CONTENTION事件。

SV LOCK:RAC环境下获取CACHE+ORDER属性的SEQUENCE.NEXTVAL时发生,对应DFS LOCK HANDLE事件。

 

使用序列号会产生跳号,序列在下列情况下出现裂缝:

回滚

系统异常

多个表同时使用同一序列

 

序列号使用:

— 返回序列中下一个有效的值,任何用户都可以引用

SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL;

— 序列的当前值

SELECT SEQUENCE_NAME.CURRVAL FROM DUAL;

 

实例应用:实现ID的自动递增

创建序列号

CREATE SEQUENCE TEST_SEQ INCREMENT BY 1 START WITH 1 MAXVALUE 30000 MINVALUE 1

CACHE 2;

 

创建表

CREATE TABLE TEST_TABLE(

ID NUMBER(6),

NAME VARCHAR2(30),

CONSTRAINT PK_ID PRIMARY KEY(ID)

);

 

插入数据

INSERT INTO TEST_TABLE VALUES(TEST_SEQ.NEXTVAL,’TOM’);

COMMIT;

 

查看数据库中的序列号:

SELECT * FROM USER_SEQUENCES;

SELECT * FROM ALL_SEQUENCES;

SELECT * FROM DBA_SEQUENCES;

 

修改序列号:

ALTER SEQUENCE SEQUENCE_NAME

[INCREMENT BY N]

[{MAXVALUE N | NOMAXVALUE}]

[{MINVALUE N | NOMINVALUE}]

[{CYCLE | NOCYCLE}]

[{CACHE N | NOCACHE}];

 

不能修改序列的初始值,否则会报ORA-02283:无法更改启动序列号

 

删除序列号:

DROP SEQUENCE [SCHEMA.]序列名;


留下一个回复

你的email不会被公开。