In Oracle 12c we have two new keywords to create sequences: SESSION and GLOBAL as you can see in the following image that was taken from Oracle Database 12c SQL Reference:
The definitions of these two types of Sequences are simple:
SESSION: The values of the sequences are unique for every session in the database. This means that with every session the sequence will start from the beginning (the first value), all the values are isolated across sessions.
GLOBAL: This means the values of the sequences are across sessions. In other words, with every session you will take a new value from the sequence, this value is the next value, not from the beginning. But there is another interesting thing here, it is also "across Primary-Standby databases". This means that if you query the sequence from a read only physical standby database you will receive the new value of the sequence, that's why is called "global". Basically is global because it is across sessions but also involves the physical standby.
I like to show examples, let's start from the basic. For these examples I will use three sessions, I will use colors to identify them easier.
- Sessions from Primary (black color and blue color).
- Sessions from Standby (green color).
Session Sequences:
Session #1 in Primary Database:
[oracle@db12102 ~]$ sqlplus user1/user1@db1
SQL> create sequence session_seq session;
Sequence created.
SQL> select sequence_name, cache_size, increment_by from user_sequences;
SEQUENCE_NAME CACHE_SIZE INCREMENT_BY
--------------- ---------- ------------
SESSION_SEQ 20 1
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_US DB_ROLE SESSION_ID
---------- ---------- ----------
USER1 PRIMARY 2500123
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
2
As you see the values of the sequence started from the beginning, in this case the value "1" because we created the sequence with all the default values for the options.
Session #2 in Primary:
Now let's Open another session with the same user :
[oracle@db12102 ~]$ sqlplus user1/user1@db1
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_US DB_ROLE SESSION_ID
---------- ---------- ----------
USER1 PRIMARY 2510101
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
2
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
3
The values started again from the beginning (value 1) because all the values already used from the session #1 were isolated, since this is a new session, the sequence will be as if it was never used. Another thing that you have to know is that the values are not stored, when the session is closed (or killed) everything will start again from the beginning, this makes sense.
Session #3 in Standby Database:
[oracle@db12102 ~]$ sqlplus user1/user1@db1s
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- ----------------- ----------
USER1 PHYSICAL STANDBY 4294967295
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select session_seq.nextval from dual;
NEXTVAL
----------
2
And just to show you that we can also use the sequence from the standby database (db1s) I am putting this example, but as you already saw ( and expected ) since the session from the standby is a "new session" the values of the sequence started from the beginning.
Global Sequences with NO ORDER and CACHE:
Now it is more interesting because we are creating a global session using cache and also using no order for the values. Let's see why these values are important when we are working with global sequences:
Session #1 from Primary:
[oracle@db12102 ~]$ sqlplus user1/user1@db1
SQL> create sequence global_seq global;
Sequence created.
SQL> select sequence_name, cache_size, increment_by from user_sequences;
SEQUENCE_NAME CACHE_SIZE INCREMENT_BY ORDER
--------------- ---------- ------------ -----
GLOBAL_SEQ 20 1 N
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_US DB_ROLE SESSION_ID
---------- ---------- ----------
USER1 PRIMARY 2530102
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
2
Since this is the first session that uses the sequence the values started from "1", but let's see what happens when we query the sequence from a second session:
Session #2 from Primary:
[oracle@db12102 ~]$ sqlplus user1/user1@db1
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- ---------- -------------
USER1 PRIMARY 2530103
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
3
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
4
Yes, as you see, the behavior of the sequence is the same of the sequences from old versions of Oracle Database, the values are across sessions, and also those values are stored so that new sessions will take new values from the sequence. The most interesting thing is when we have a read-only Physical Standby like in the following example:
Session #3 from Standby:
[oracle@db12102 ~]$ sqlplus user1/user1@db1s
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- ---------------- ---------------
USER1 PHYSICAL STANDBY 4294967295
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
21
SQL> select global_seq.nextval from dual;
NEXTVAL
----------
22
SQL>
This is a third session, opened from a read-only Physical Standby Database and look at the values that were returned from the sequence, the first value returned was "21", this is because the sequence was created with a cache size of "20", this means that 20 values were loaded in the Primary Database Instance, and here in the Physical Standby Instance a new set of values were taken starting with "21", but it is interesting that the sequences now are across Primary-Standby databases.
Global Sequences with NO ORDER and NO CACHE:
Now let's change the options, now let's use values with no oder and no cache and let's see what happens:
Session #1 from Primary:
[oracle@db12102 ~]$ sqlplus user1/user1@db1
SQL> create sequence global_nocache_seqglobal nocache;
Sequence created.
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_US DB_ROLE SESSION_ID
---------- ---------- ----------
USER1 PRIMARY 2540100
SQL>
SQL> select sequence_name, cache_size, increment_by , order_flag from user_sequences;
SEQUENCE_NAME CACHE_SIZE INCREMENT_BY ORDER
-------------------- ---------- ------------ -----
GLOBAL_NOCACHE_SEQ 0 1 N
SQL> select global_nocache_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select global_nocache_seq.nextval from dual;
NEXTVAL
----------
2
Session #2 from Standby:
[oracle@db12102 ~]$ sqlplus user1/user1@db1s
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- ----------------- ---------------
USER1 PHYSICAL STANDBY 4294967295
SQL> select global_nocache_seq.nextval from dual;
select global_nocache_seq.nextval from dual
*
ERROR at line 1:
ORA-03179: NOCACHE or ORDER sequences cannot be accessed from Active Data Guard standby
Look at that error, the error clearly says that we cannot use that sequence from the read-only Physical Standby because the sequence was not created using "cache" and using "no order". This is important and I wanted to show you that, that's why I created this scenario, because if you want to use sequences from the read-only Physical Standby Database you have to know that you must create the sequence using CACHE and NO ORDER otherwise you will get errors in the Standby site. Just to confirm what I am saying I will create the last scenario, where I am using Cache but I am not using values with order.
Global Sequences with ORDER and CACHE:
Session #1 from Primary:
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- --------------- ---------------
USER1 PRIMARY 2630100
SQL> create sequence global_order_seqglobal order;
Sequence created.
SQL> select sequence_name, cache_size, increment_by , order_flag from user_sequences;
SEQUENCE_NAME CACHE_SIZE INCREMENT_BY ORDER
-------------------- ---------- ------------ -----
GLOBAL_ORDER_SEQ 20 1 Y
SQL> select global_order_seq.nextval from dual;
NEXTVAL
----------
1
SQL> select global_order_seq.nextval from dual;
NEXTVAL
----------
2
Session #2 from Standby:
[oracle@db12102 ~]$ sqlplus user1/user1@db1s
SQL> SELECT SYS_CONTEXT ('USERENV','SESSION_USER') session_user, SYS_CONTEXT ('USERENV','DATABASE_ROLE') db_role, SYS_CONTEXT ('USERENV','SESSIONID') session_id FROM DUAL;
SESSION_USER DB_ROLE SESSION_ID
--------------- --------- ---------------
USER1 PHYSICAL STANDBY 4294967295
SQL> select global_order_seq.nextval from dual;
select global_order_seq.nextval from dual
*
ERROR at line 1:
ORA-03179: NOCACHE or ORDER sequences cannot be accessed from Active Data Guard standby
As you see, the result is the same. This confirms we must use CACHE and NO ORDER if we want to use the sequences from the read-only Physical Standby.
Follow me: