0

前回、本番環境でストアド プロシージャを実行中に ORA-00001 に遭遇しました。ストアド プロシージャは昨日まで正常に動作していましたが、トラブルシューティングを試みましたが、どこにも行きませんでした。

以下でいくつかの有用な考えを提供していただければ幸いです..

状況を次のように分類しました: 1) 主キーを持つテーブル、2) シーケンス、3) ストアド プロシージャ。

1) 以下のメインテーブルがあります。

CREATE TABLE MY_MESSAGES (MESSAGE_ID NUMBER, MESSAGE VARCHAR2(200));
CREATE UNIQUE INDEX MY_MESSAGES_PK ON MY_MESSAGES (MESSAGE_ID);
ALTER TABLE MY_MESSAGES ADD CONSTRAINT MY_MESSAGES_PK PRIMARY KEY (MESSAGE_ID) USING INDEX  ENABLE;

2) シーケンス

CREATE SEQUENCE  MESSAGE_ID_SEQUENCE;

独立したバックアップ テーブル:

CREATE TABLE MY_MESSAGES_BKP (BKP_ID VARCHAR2(200), RECIVED_TIME TIMESTAMP, MESSAGE VARCHAR2(200));
INSERT INTO MY_MESSAGES_BKP VALUES('201', TIMESTAMP '2018-09-26 00:00:00.000000', 'MSG206');
INSERT INTO MY_MESSAGES_BKP VALUES('202', TIMESTAMP '2018-09-26 05:00:00.000000', 'MSG206');
INSERT INTO MY_MESSAGES_BKP VALUES('203', TIMESTAMP '2018-09-26 06:00:00.000000', 'MSG207');
INSERT INTO MY_MESSAGES_BKP VALUES('204', TIMESTAMP '2018-09-26 07:00:00.000000', 'MSG208');
INSERT INTO MY_MESSAGES_BKP VALUES('205', TIMESTAMP '2018-09-26 08:00:00.000000', 'MSG209');
COMMIT;

3) そして最後に、ストアド プロシージャ:

DECLARE
  TYPE VARCHAR_TABLE IS TABLE OF VARCHAR(200);
  V_MESSAGE_ID NUMBER(20) := 0;
  V_BKP_IDS VARCHAR_TABLE := VARCHAR_TABLE();
  V_EXC_QUERY VARCHAR2(200) := 'INSERT INTO MY_MESSAGES(MESSAGE_ID, MESSAGE) SELECT :1, MESSAGE FROM  MY_MESSAGES_BKP WHERE BKP_ID = :2';
BEGIN
  SELECT BKP_ID BULK COLLECT INTO V_BKP_IDS FROM MY_MESSAGES_BKP WHERE RECIVED_TIME > TIMESTAMP '2018-09-26 00:00:00.000000';

  FOR I IN 1..V_BKP_IDS.COUNT LOOP
    EXECUTE IMMEDIATE 'SELECT MESSAGE_ID_SEQUENCE.NEXTVAL FROM DUAL' INTO V_MESSAGE_ID ;
    EXECUTE IMMEDIATE V_EXC_QUERY USING V_MESSAGE_ID, V_BKP_IDS(I);
  END LOOP;
  V_BKP_IDS.DELETE;
EXCEPTION
    WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLERRM); 
END;
/

それを知っていると、テーブル MY_MESSAGES は、主キーに同じシーケンス (MESSAGE_ID_SEQUENCE) を使用する他のプロセスによって使用されます。

ストアド プロシージャはしばらく実行されていましたが、〜 5000 レコードのうち 400 を超えるレコードが挿入されました。その後、次のエラーで停止しました。

ORA-00001: unique constraint my_messages_pk) violated

さらに、テーブルを調査した結果、正常に挿入されたレコードのすべての主キーが、停止する前にシーケンシャルであることがわかりました..

他のプロセスはバックグラウンドで完全に正常に実行されており、挿入されたレコードもシーケンシャルですが、ストアド プロシージャによって挿入された最後のレコードと他のプロセスによって挿入された次のレコードの間に 1 つの数値のギャップがあることがわかります。

これは、MESSAGE_ID_SEQUENCE.NEXTVAL がストアド プロシージャによって実行されたが、レコードが挿入されなかったことを意味します。

ストアド プロシージャが停止した場合、テーブルには主キーを持つレコードがありません。

何がうまくいかなかったのでしょうか?さらに詳しく調べるにはどうすればよいでしょうか。

4

1 に答える 1