Oracle的Sequence对象是我们经常使用的一种生成唯一性数据序列的工具对象。数字类型列配合Sequence对象,可以方便的实现主键列功能。本片介绍使用Sequence对象时,需要关注的两个问题。
实验环境准备
首先构建一个实验的序列对象seq_t。
//序列化对象
SQL> create sequence seq_t;
Sequence created
此时,seq_t的构建信息和默认值分别为。
--构造参数获取
-- Create sequence
create sequence SEQ_T
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
cache 20;
从默认值信息看,sequence对象相关的参数包括五个类型,分别表示sequence工作方式和当前信息。
ü Minvalue:表示当前sequence所能够使用的最小值。
ü Maxvalue:序列可以取到的最大值。如果序列类型是recycle的,则当前sequence重新回到minvalue;
ü Startwith表示下一次直接访问sequence对象时获取到的值;
ü Cache是每次进行缓存的数据量;
关于Currval和nextval两个方法的使用
Sequence对象的两个方法seq_name.currval和seq_name.nextval分别用于访问指定sequence对象当前的sequence取值和获取一个新值。下面我们进行一系列的实验。
首先,开启会话一,注意此时sequence创建之后,并没有使用。Minvalue同start with值一样。
SQL> select sid from v$mystat where rownum<2;
SID
----------
147
select seq_t.currval from dual
ORA-08002: 序列 SEQ_T.CURRVAL 尚未在此会话中定义
注意,我们在这里看到了currval方法的一个特点。当在一个新的会话中,没有使用过nextvalue方法时,currval方法是不能调用的,调用是要报错ora-08002。报错提示信息声明说要求该序列在会话中进行声明,意味着currval是一个会话绑定的方法。
//第一次调用,
SQL> select seq_t.nextval from dual;
NEXTVAL
----------
1
//当在当前会话中调用过一次nextval之后,currval在紧接着的调用中就可以生效了;
SQL> select seq_t.currval from dual;
CURRVAL
----------
1
上面的实验,已经使我们获得了一个结论:sequence对象的currval方法是不能够单独调用的,在会话中一定要配合nextval方法之后,才能获取到刚刚调用的值;
下面继续开启另一个会话。
SQL> select sid from v$mystat where rownum<2;
SID
----------
153
SQL> select seq_t.currval from dual;
select seq_t.currval from dual
ORA-08002: 序列 SEQ_T.CURRVAL 尚未在此会话中定义
SQL> select seq_t.nextval from dual;
NEXTVAL
----------
2
SQL> select seq_t.currval from dual;
CURRVAL
----------
2
注意,虽然我们在会话一(sid=147)中使用了seq_t,并且使用了取值1,但是在另一个会话中,依然不能通过currval去获取到。说明currval方法是会话绑定,与sequence全局无关,必须与nextval配合使用。只有显示调用一次nextval之后,才能在会话中调用currval取值。
此时的sequence定义为:
-- Create sequence
create sequence SEQ_T
minvalue 1
maxvalue 999999999999999999999999999
start with 21
increment by 1
cache 20;
由于使用cache的原因,Oracle对当前seq_t的start with参数去定位21,出现跳号。这部分内容在后面详细介绍。
此时,我们回到会话一中,检查currval的情况。
SQL> select seq_t.currval from dual;
CURRVAL
----------
1
虽然我们在会话二中,已经将seq_t的取值推进到2。但是会话一还是记录着先前自己的1,没有同步推进。
结论:我们可以看到Currval使用的一个重要特征就是会话绑定特性。进入会话的时候,seq_t在当前会话是没有当前值的。只有在显示调用nextval方法之后,才会在会话内部保留一个取值。而这个取值是不会随着其他会话推进seq取值而更新的。
这也就是解释了currval方法受限制的方面。Currval方法是不能够真实反映sequence对象全局当前取值,而是会话内部上次调用的取值。这一点在开发过程中一定注意。
Cache参数
Cache参数是sequence对象的一个重要参数。Sequence是在Oracle并行访问系统中的一个串行单位,保证并行操作获取到的数值序列不会重合。本质上,sequence内部必然存在一种latch机制来保证其中的串行特性。
如果系统中广泛使用sequence,而且并发访问sequence的会话很多。那么必然存在频繁的latch现象,成为一种系统性能瓶颈。Cache参数就是解决这个问题的一种方案。
Cache的思路是这样。每次从要求访问Sequence数值,都是进行latch操作,每次不是只获取到一个数值,而是获取到Cache数量个数值存放在内存中。下次来访问获取新取值时,就不需要再次调用latch,而是分配内存中的数据值。这样就避免了过多的latch引发性能问题。
--刷新
SQL> alter system flush shared_pool;
系统已更改。
SQL> alter system flush buffer_cache;
系统已更改。
SQL> select sid from v$mystat where rownum<2;
SID
----------
147
SQL> select seq_t.nextval from dual;
NEXTVAL
----------
21
我们借助将内存flush之后,发现再次调用就出现了新的数字21,而不是3。这些就说明了缓存cache在起作用。将内存中的20个数字flush出之后,只能重新调用seq_t形成新值。
Cache机制缓解了latch系统争用的情况,但是随之而来的问题就是跳号问题。如果我们生成的sequence取值只是需要唯一不重复,发生跳号问题影响不大。如果数值具有一定的业务含义或者要求必须连续,我们就只能设置nocache参数情况了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-693121/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-693121/