I have a sequence SEQ_PAGE_ID

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

To change the CACHE_SIZE, I used below script,

alter sequence SEQ_PAGE_ID CACHE 5000;

When I checked the query,

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


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

The LAST_NUMBER changed from 2222292456 to 2222292447. Is this happened due to the alter script?

有帮助吗?

解决方案

This is normal, yes. From the documentation for the all_sequences data dictionary view, last_number is:

Last sequence number written to disk. If a sequence uses caching, the number written to disk is the last number placed in the sequence cache. This number is likely to be greater than the last sequence number that was used.

This can be recreated with a fresh sequence:

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 

The last_number jumped up by the cache size, which is normal.

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 

The last_number goes down, but now reflects the actual last sequence number generated. The DDL has (apparently) caused the data written to disk to be updated to reflect what happens to be the current value, rather than the top of the cache - either the old 20-value cache or the new 5000-value cache. In your case you got 2222292447, which just means you were ten values further through the cache than I was when I ran the alter.

The value saved to disk is largely there so that if the database crashes it knows where to pick up from. On restart the sequence will start generating numbers from the recorded last_number. During normal running it doesn't need to refer back to that, it just updates the value on disk when new values are cached. This prevents sequence numbers being reissued after a crash, without needing to do expensive (slow) locking to maintain the value in real time - which is what the cache is there to avoid, after all.

There would only be a problem if the last_value was lower than an actual generated sequence, but that can't happen. (Well, unless the sequence is set to cycle).

SQL> select SEQ_PAGE_ID.nextval from dual;

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

The next sequence number generated follows on from the last one before the cache size change; it hasn't reused an old value as you might have been worried about from the dictionary value.

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 

The last_number now shows the previous stored value incremented by the cache size of 5000. What is in the data dictionary now won't change again until we've consumed all 5000 values form the cache, or something happens elsewhere that affects it - the database being bounced, the sequence being altered again, etc.

其他提示

When the sequence is in cache, last_number represent the number keep by oracle. When not, it represents the last sequence use by Oracle. With your alter command, you change the settings of the sequence, so Oracle flush it's "sequence cache"

Here a simple example

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> 

This post is for changing Last Number :)

Let us assume LAST_NUMBER in seq xyz is 3953 and you want to change it to 205233, then you need to increment the sequence by (205233 - 3953 = 201,280) and then increment it by 1. that can be achieved by below statements:

to change the LAST_NUMBER to

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

Now the LAST_NUMBER would be updated as 205233

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top