关于oracle序列的LAST_NUMBER

时间:2014-05-13 12:43:17

标签: oracle

我有序列SEQ_PAGE_ID

SEQUENCE_NAME   INCREMENT_BY  CACHE_SIZE   LAST_NUMBER            
-------------------------------------------------------
SEQ_PAGE_ID      1              20          2222292456 

要更改CACHE_SIZE,我使用下面的脚本

alter sequence SEQ_PAGE_ID CACHE 5000;

当我查看查询时,

select ... from user_sequences where sequence_name  = 'SEQ_PAGE_ID';


SEQUENCE_NAME   INCREMENT_BY  CACHE_SIZE    LAST_NUMBER            
-------------------------------------------------------
SEQ_PAGE_ID      1              5000          2222292447 

LAST_NUMBER已从2222292456更改为2222292447。 这是因为改变脚本而发生的吗?

2 个答案:

答案 0 :(得分:14)

这是正常的,是的。从documentation for the all_sequences data dictionary view开始,last_number是:

  

写入磁盘的最后序列号。如果序列使用缓存,则写入磁盘的编号是序列缓存中的最后一个编号。该数字可能大于最后使用的序列号。

可以使用新序列重新创建:

SQL> create sequence SEQ_PAGE_ID start with 2222292436 increment by 1 cache 20;

sequence SEQ_PAGE_ID created.

SQL> select sequence_name, increment_by, cache_size, last_number
  2  from user_sequences where sequence_name = 'SEQ_PAGE_ID';

SEQUENCE_NAME                  INCREMENT_BY CACHE_SIZE LAST_NUMBER
------------------------------ ------------ ---------- -----------
SEQ_PAGE_ID                               1         20  2222292436 

SQL> select SEQ_PAGE_ID.nextval from dual;

   NEXTVAL
----------
2222292436 

SQL> select sequence_name, increment_by, cache_size, last_number
  2  from user_sequences where sequence_name = 'SEQ_PAGE_ID';

SEQUENCE_NAME                  INCREMENT_BY CACHE_SIZE LAST_NUMBER
------------------------------ ------------ ---------- -----------
SEQ_PAGE_ID                               1         20  2222292456 

last_number跳过缓存大小,这是正常的。

SQL> alter sequence SEQ_PAGE_ID CACHE 5000;

sequence SEQ_PAGE_ID altered.

SQL> select sequence_name, increment_by, cache_size, last_number
  2  from user_sequences where sequence_name = 'SEQ_PAGE_ID';

SEQUENCE_NAME                  INCREMENT_BY CACHE_SIZE LAST_NUMBER
------------------------------ ------------ ---------- -----------
SEQ_PAGE_ID                               1       5000  2222292437 

last_number下降,但现在反映了生成的实际最后序列号。 DDL(显然)导致写入磁盘的数据被更新以反映当前值,而不是缓存的顶部 - 旧的20值缓存或新的5000值缓存。在你的情况下,你得到了2222292447,这意味着你在缓存中的值比我运行alter时的值要多十个。

保存到磁盘的值很大程度上存在,因此如果数据库崩溃,它知道从哪里拿起。重新启动时,序列将开始从记录的last_number生成数字。在正常运行期间,它不需要再引用它,它只是在缓存新值时更新磁盘上的值。这可以防止序列号在崩溃后重新发布,而无需进行昂贵的(慢速)锁定来实时维护该值 - 毕竟这是缓存所要避免的。

如果last_value低于实际生成的序列,则只会出现问题,但这种情况不会发生。 (好吧,除非序列设置为循环)。

SQL> select SEQ_PAGE_ID.nextval from dual;

   NEXTVAL
----------
2222292437 

生成的下一个序列号从缓存大小更改之前的最后一个序列号开始;它没有重用旧值,因为你可能一直担心字典值。

SQL> select sequence_name, increment_by, cache_size, last_number
  2  from user_sequences where sequence_name = 'SEQ_PAGE_ID';

SEQUENCE_NAME                  INCREMENT_BY CACHE_SIZE LAST_NUMBER
------------------------------ ------------ ---------- -----------
SEQ_PAGE_ID                               1       5000  2222297437 

last_number现在显示先前存储的值增加了5000的缓存大小。数据字典中的内容现在不会再次更改,直到我们从缓存中消耗了所有5000个值,或其他影响它的事情 - 数据库被反弹,序列再次被改变等等。

答案 1 :(得分:6)

当序列在缓存中时,last_number表示由oracle保留的数字。 如果没有,它代表Oracle使用的最后一个序列。 使用您的alter命令,您可以更改序列的设置,以便Oracle将其清除"序列缓存"

这是一个简单的例子

SQL> drop sequence test;
Sequence dropped

SQL> create sequence test cache 20;
Sequence created

SQL> select last_number  from user_sequences where sequence_name='TEST';
LAST_NUMBER
-----------
          1

SQL> select test.nextval from dual;
   NEXTVAL
----------
         1

SQL>  select last_number  from user_sequences where sequence_name='TEST';
LAST_NUMBER
-----------
         21

SQL> alter sequence test CACHE 5000;
Sequence altered

SQL>  select last_number  from user_sequences where sequence_name='TEST';
LAST_NUMBER
-----------
          2

SQL> select test.nextval from dual;
   NEXTVAL
----------
         2

SQL>  select last_number  from user_sequences where sequence_name='TEST';
LAST_NUMBER
-----------
       5002

SQL>