【问题标题】:LAST_NUMBER on oracle sequence预言机序列上的 LAST_NUMBER
【发布时间】:2022-02-09 00:42:12
【问题描述】:

我有一个序列 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_NUMBER2222292456 更改为 2222292447。 这是由于更改脚本而发生的吗?

【问题讨论】:

标签: oracle


【解决方案1】:

这是正常的,是的。来自documentation for the all_sequences data dictionary viewlast_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 个值,或者其他地方发生了影响它 - 数据库被退回,序列再次被改变,等等。

【讨论】:

    【解决方案2】:

    当序列在缓存中时,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> 
    

    【讨论】:

      【解决方案3】:

      这篇文章是为了更改 Last Number :)

      让我们假设 seq xyz 中的 LAST_NUMBER 是 3953 并且您想将其更改为 205233,那么您需要将序列增加 (205233 - 3953 = 201,280),然后将其增加 1。这可以通过以下语句实现:

      将 LAST_NUMBER 更改为

      ALTER SEQUENCE xyz INCREMENT BY 201280;
      SELECT xyz.nextval from dual;
      ALTER SEQUENCE xyz INCREMENT BY 1;
      

      现在 LAST_NUMBER 将更新为 205233

      【讨论】:

        猜你喜欢
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-07
        • 1970-01-01
        • 1970-01-01
        • 2019-04-14
        相关资源
        最近更新 更多