シーケンス(順序)で欠番が発生する原因5つ

ORACLE
20170302-2

ORACLEのシーケンス(順序)で欠番が発生することがあります。

本記事ではその原因について、まとめました。

スポンサーリンク

シーケンスで欠番が発生!

シーケンスは、一意の値を生成するのに非常に便利です。

例えば、1から採番を開始、1つずつカウントアップするシーケンスを作成し、受注データの伝票番号を自前で採番する時に使用するといった使い方をします。

1つずつカウントアップするので、基本的には欠番は発生しないはずです。しかし、欠番が起きることがあります。

-- receive_order(受注テーブル)
--  1.customer_id(得意先ID)
--  2.order_no(伝票番号) ← シーケンスを利用して採番
--  3.insert_date(登録日)

CUSTOMER_ID ORDER_NO   INSERT_DATE
----------- ---------- -----------
00100       0000000001 20170301
00200       0000000002 20170301
00100       0000000003 20170302
00300       0000000021 20170303     ← 伝票番号が欠番している
00300       0000000022 20170303
スポンサーリンク

欠番が発生する原因

シーケンスを利用していて欠番が発生する原因は、以下の5つが考えられます。

ロールバック

ロールバックでデータの更新を取り消しても、カウントアップしたシーケンスは元に戻りません。トランザクション中にORACLEがダウンした場合も、再起動時のインスタンスリカバリでロールバックされるので同様に欠番が発生します。

SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
    1

ROLLBACK;

SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
    2

ORACLEの再起動

ORACLEを再起動すると、事前にキャッシュしておいた値がクリアされてしまうため欠番が発生します。

シーケンスのキャッシュは、処理速度向上のために共有プール上に事前にシーケンスから値を取得して保持しておく機能です。

ORACLEを再起動すると、共有プールがクリアされてしまうため、キャッシュしておいたシーケンス値もクリアされ、結果として欠番となってしまいます。シーケンスをキャッシュしない設定の場合は発生しません。

-- キャッシュ20
SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
    1

~ORACLE再起動~

SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
   21

キャッシュは、初回のシーケンスアクセス時と、キャッシュされた値を使い切った時に行われます。つまり、ORACLE起動後、一度もシーケンスにアクセスしていない状態でORACLEの再起動があっても、欠番は発生しません。

また、RAC環境の場合は、各ノードごとにキャッシュが行われているので、RACを構成する内の1つのノードが再起動した場合でも、欠番が発生します。

共有プールのクリア

明示的に共有プールのクリアを行った場合も、欠番が発生します。

これについても、シーケンスをキャッシュしない設定の場合は発生しません。

-- キャッシュ20
SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
    1

-- 共有プールのクリア
ALTER SYSTEM FLUSH SHARED_POOL;

SELECT test_seq1.NEXTVAL a FROM DUAL;
    A
-----
   21

共有プールからエージアウト

共有プールにキャッシュしておいたシーケンス値ですが、しばらく使用していないと共有プールから追い出されます(エージアウト)。結果、欠番が発生します。

これについても、シーケンスをキャッシュしない設定の場合は発生しません。

人為的原因

本来、シーケンスを使用しているアプリケーション外でシーケンスを使用された場合、欠番が発生します。

現在のシーケンス値を確認するために、実際に【シーケンス.NEXTVAL】で値を取得していたシステム担当者がいたために、欠番が発生していた経験があります。

欠番は普通に発生する

ここまで見てきたように、欠番は普通に発生する現象です。

シーケンスを使用する場合は、欠番が発生しても問題とならないような設計にする必要があります。

まとめ

ORACLEのシーケンス(順序)の欠番、人為的な原因を除けば、ロールバックと、共有プールからキャッシュされたシーケンス値がクリアまたはキャッシュアウトされた場合に発生します。

欠番は普通に発生する現象ですので、シーケンスを使用する場合は、欠番が発生しても問題とならないような設計にしましょう。

関連



タイトルとURLをコピーしました