数据库序列

数据库序列

在ORACLE数据库中,什么是序列呢?它的用途是什么?

序列其实是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值。(类型为数字),其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增加至下一个值。

创建序列:

1
2
3
4
5
6
创建序列需要CREATE SEQUENCE系统权限。序列的创建语法如下:
CREATE SEQUENCE 序列名
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE/ MINVALUE n|NOMAXVALUE}] []
[{CACHE n|NOCACHE}];

说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
INCREMENT BY 用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表序列的值是按照此步长递减的。
START WITH 定义序列的初始值(即产生的第一个值),默认为1。
MAXVALUE 定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项,代表没有最大值定义,这时对于递增序列,系统能够产生的最大值是10的27次方;对于递减序列,最大值是-1。
MINVALUE定义序列生成器能产生的最小值。选项NOMAXVALUE是默认选项,代表没有最小值定义,这时对于递减序列,系统能够产生的最小值是?10的26次方;对于递增序列,最小值是1。
cache讲解:
如果指定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在高并发访问时,容易导致rowcache lock等待事件,
主要原因是每次获取nextval时都需要修改rowcache中的字典信息。
使用nocache sequence,还会导致如下问题:
由于每次修改字典信息都需要commit,可能导致log file sync等待,nocache sequence在RAC环境下,
会对基于sequence生成的列创建的索引造成实例间大量索引块争用
基于以上问题,避免创建nocache sequence。

sequence相关保护机制:

1
2
3
row cache lock:在调用sequence.nextval情况下需要修改数据字典时发生,对应rowcache lock事件
SQ lock:在内存缓存(并非rowcache)上获取sequence.nextval时发生,对应enq:SQ-contention事件
SV lock:RAC环境下获取cache+order属性的sequence.nextval时发生,对应DFS lock handle事件

创建一个名称为:SEQUENCE_PARAMID 的序列:

1
2
3
4
5
6
CREATE SEQUENCE SEQUENCE_PARAMID
INCREMENT BY 1
MINVALUE 100001001
MAXVALUE 999999999
NOCYCLE
NOCACHE;

感受:
2017年5月份,行内要做学费缴费,银联的POS流水号要传6位不能重复数字,用时间戳不够长度做唯一性识别,所以设计了序列,但是序列的位数怎么确定呢?
这里再用到SQL的一个语句:只要不足6位就在前边补0。这个还是周晓靖教我的哈哈,谢谢小静。

1
select lpad(posSeq.nextval,6,'0') from dual;

什么情况下使用cache什么时间上使用nocache?
我个人感觉应该尽量使用cache,因为现在的数据库很多都是在高并发的情况下运行的,首先这样可以搞性能,并且也不会产生rowcache lock等待事件。
可能有些人会担心数据库不正常的down掉会产生序列号间断,但这也是很少的情况。当然如果你的业务要求是绝不能产生间断的序列号,那就要使用nochache了。

|