oracle获取序列跳号,Oracle sequence跳号知多少
Sequence是oracle中的一個非常常用的功能,開發經常會頻繁使用。但是在生產環境中經常有應用反饋通過sequence生成的自增主鍵會出現不連續跳號的現象,而且是幾十個幾十個地跳,為了弄清楚sequence跳號的原因和機制,進行了一些研究和實驗。
事務回滾引起的跳號
不管序列有沒有CACHE、事務回滾這種情況下,都會引起序列的跳號。如下實驗所示:
SQL> create sequence test_seq
start with 1
increment by 1
Maxvalue 9999999999
Cache 30
Order;
Sequence created.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
1
SYS@orcl>insert into test_tab select test_seq.nextval from dual;
1 row created.
SYS@orcl>rollback;
Rollback complete.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
3
并發訪問序列引起的跳號
并發訪問序列引起的跳號,其實不算真正的跳號,而只是邏輯跳號,只是序列值被其它并發會話使用了。我們來構造一起并發訪問序列引起的跳號,我們開啟兩個會話窗口,循環獲取序列的值,模擬并發出現的場景。
Session 1:
SYS@orcl>begin
for i in 1..50000 loop
Insert into ta select test_seq.nextval from dual;
end loop;
end;
/
PL/SQL procedure successfully completed.
Session 2:
SYS@orcl>begin
for i in 1..50000 loop
insert into tb select test_seq.nextval from dual;
end loop;
end;
/
PL/SQL procedure successfully completed.
SYS@orcl>select * from ta where rownum<10;
ID
----------
466322
466324
466326
466327
466329
466330
466332
466333
466335
9 rows selected.
發現序號并不連續,高并發情況下存在sequence爭用。
FLUSH SHARED_POOL會導致CACHE的序列跳號
實驗測試如下所示(序列的CACHE值必須大于0),當然正常情況下,很難遇到這種情況。
SYS@orcl>alter sequence test_seq cache 30;
Sequence altered.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560432
SYS@orcl>alter system flush shared_pool;
System altered.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560462
數據庫實例異常關閉導致跳號
如下實驗所示,當數據庫使用shutdown abort命令關閉后,重新啟動實例,序列緩存在shared pool里面沒有用過的值都沒有了。一下子從17045跳到17085
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560464
SYS@orcl>select object_id from dba_objects where object_name='TEST_SEQ';
OBJECT_ID
----------
20306
SYS@orcl>select increment$,minvalue,maxvalue,highwater,cache from seq$ where obj#=20306;
INCREMENT$ ??MINVALUE ??MAXVALUE ?HIGHWATER ?????CACHE
---------- ---------- ---------- ---------- ----------
1 ??????????1 ??9999999999 ????560492 ????????30
SYS@orcl>shutdown abort;
ORACLE instance shut down.
SYS@orcl>startup;
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560492
而在正常關閉數據庫的情況下,sequence沒有發生跳號
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560526
SYS@orcl>shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS@orcl>startup;
ORACLE instance started.
Total System Global Area 4375998464 bytes
Fixed Size ?????????????????2260328 bytes
Variable Size ???????????1946157720 bytes
Database Buffers ????????2415919104 bytes
Redo Buffers ??????????????11661312 bytes
Database mounted.
Database opened.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560527
設置test_seq為nocache,然后異常宕機
SYS@orcl>alter sequence test_seq nocache;
Sequence altered.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560528
SYS@orcl>shutdown abort;
ORACLE instance shut down.
SYS@orcl>startup;
ORACLE instance started.
Total System Global Area 4375998464 bytes
Fixed Size ?????????????????2260328 bytes
Variable Size ???????????1946157720 bytes
Database Buffers ????????2415919104 bytes
Redo Buffers ??????????????11661312 bytes
Database mounted.
Database opened.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560529
查閱資料發現數據庫正常關閉的情況下,會觸發一個update seq$的操作,把當前的sequence.nextval的值更新到seq$.highwater中,從而使得sequence在有cache的情況下,數據庫正常關閉未出現nextval跳躍(currval也同樣不跳躍);而在數據庫異常關閉之時,數據庫不能及時將sequence.nextval更新到eq$.highwater從而引起sequence cache中的值丟失,從而可能出現了sequence使用cache導致跳躍的情況
MOS(文檔ID:470784.1)上提到了使用dbms_shared_pool.keep將對象在鎖定在shared pool 中,永遠不釋放。這樣可以防止FLUSH SHARED POOL導致序列跳號,但是這個無法避免數據庫異常關閉或CRASH引起的跳號
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560530
SYS@orcl>exec dbms_shared_pool.keep('test_seq','q');
PL/SQL procedure successfully completed.
SYS@orcl>alter system flush shared_pool;
System altered.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560531
SYS@orcl>alter sequence test_seq cache 30;
Sequence altered.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560532
SYS@orcl>shutdown abort
ORACLE instance shut down.
SYS@orcl>startup;
ORACLE instance started.
Total System Global Area 4375998464 bytes
Fixed Size ?????????????????2260328 bytes
Variable Size ???????????1946157720 bytes
Database Buffers ????????2415919104 bytes
Redo Buffers ??????????????11661312 bytes
Database mounted.
Database opened.
SYS@orcl>select test_seq.nextval from dual;
NEXTVAL
----------
560562
其實如果業務允許,單號出現跳號也無所謂的情形最好,如果碰到業務要求絕對不能出現單號出現跳號的情況,那么就不能使用序列號了。
RAC環境中的sequence
如果是cache下的order,單實例下沒有影響,而rac下多實例緩存相同的sequence,如果order的取大量sequence則會出現短暫的資源競爭(由于資源需要在多實例間傳遞),性能要比noorder差很多。尤其注意nocache order的sequence,即對于sequence大量爭用,還需要在實例間傳遞競爭資源,嚴重的甚至導致系統直接hang住,對于rac的環境需要通過cache fusion和序列的機制認真分析來找到性能瓶頸的根本原因。
oracle為了在rac環境下為了sequence的一致性,使用了三種鎖:row cache lock、SQ鎖、SV鎖。row cache lock的目的是在sequence指定nocache的情況下調用sequence.nextval過程中保證序列的順序性;SQ鎖是應用于指定了cache+noorder的情況下調用sequence.nextval過程中。SV 鎖(dfs lock handel) 是調用sequence.nextval期間擁有的鎖。前提是創建sequence時指定了cache 和order屬性 (cache+order)。order參數的目的是為了在RAC上節點之間生成sequence的順序得到保障。
創建sequence賦予的cache值較小時,有enq:sq-contention等待增加的趨勢。cache的缺省值是20.因此創建并發訪問多的sequence時,cacheh值應取大一些。否則會發生enq:sq-contention等待事件。
rac上創建sequence時,如果指定了cache大小而賦予noorder屬性,則各節點將會把不同范圍的sequence值cache到內 存上。若兩個節點之間都必須通過依次遞增方式使用sequence,必須賦予如下的order屬性(一般不需要這樣做)”sql> create sequence seq_b cache 100 order”。如果是已賦予了cache+order屬性的sequence,oracle使用SV鎖進行同步。SV鎖爭用問題發生時的解決方法與sq鎖 的情況相同,就是將cache 值進行適當調整。
在RAC多節點環境下,Sequence的Cache屬性對性能的影響很大。應該盡量賦予cache+noorder屬性,并要給予足夠的 cache值。如果需要保障順序,必須賦予cache+order屬性。但這時為了保障順序,實例之間需要不斷的交換數據。因此性能稍差。
總結
以上是生活随笔為你收集整理的oracle获取序列跳号,Oracle sequence跳号知多少的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解读华为2022年度报告营收数字背后的故
- 下一篇: 造车新势力第一!广汽埃安3月销量4001