Исследование ORA-00001 в PL / SQL - PullRequest
       31

Исследование ORA-00001 в PL / SQL

0 голосов
/ 26 сентября 2018

Мы столкнулись с 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) для первичного ключа ..

Хранимая процедура выполнялась в течение некоторого времени и вставила более 400 записей из ~ 5000 записей .. затем она остановилась с ошибкой ниже:

ORA-00001: unique constraint my_messages_pk) violated

Более того, после исследования таблицы мы обнаружили, что все первичные ключи успешно вставленных записей были последовательными, прежде чем она остановилась ..

Другой процесс работал отличноотлично в фоновом режиме, и мы можем видеть, что вставленные записи также являются последовательными, но с интервалом в 1 число между последней записью, вставленной хранимой процедурой, и следующей вставленной записью другим процессом.

Что означает, что MESSAGE_ID_SEQUENCE.NEXTVAL был выполнен хранимой процедурой, но запись не была вставлена.

В таблицах нет записи с первичным ключом, если бы хранимая процедура была остановлена.

Что могло пойти не так?И как мы можем продолжить расследование?

1 Ответ

0 голосов
/ 26 сентября 2018

самое простое объяснение будет то, что в случае ORA-00001, этот выбор SELECT :1, MESSAGE FROM MY_MESSAGES_BKP WHERE BKP_ID = :2 обнаружил более одной строки с BKP_ID = :2.Это, в свою очередь, заставит вставку INSERT INTO MY_MESSAGES(MESSAGE_ID, MESSAGE) SELECT :1, MESSAGE FROM MY_MESSAGES_BKP WHERE BKP_ID = :2 использовать один и тот же номер из последовательности несколько раз.НТН

...