2016-10-17 7 views
0

У меня здесь странная ситуация. Я использовал триггеры и последовательности для реализации автоматического увеличения. Я вставляю данные в свои таблицы из своего веб-приложения, которое использует Hibernate. Я тестирую веб-приложение на своей машине (Netbeans), а также в своей офисной сети (веб-приложение также развертывается на нашем сервере с Wildfly).Oracle автоинкремент с последовательностью и триггером

Он всегда работал нормально, пока я не начал получать исключения из-за уникального ограничения (первичный ключ). Затем я обнаружил, что проблема заключается в последовательности, которая генерирует значения для идентификаторов. Например, для моей таблицы xtable, LAST_NUMBER его последовательность является 78400, максимальный идентификатор в xtable является 78308, но NEXTVAL Последовательность является 78304. Я понятия не имею, как это происходит потому, что я создал последовательность со следующим:

CREATE SEQUENCE XTABLE_SEQUENCE INCREMENT BY 1 START WITH 1; 

Я попытался следующие обновить последовательность и сделать его NEXTVAL больше максимального (ID) в таблице, но я все еще получаю тот же результат после того, как п вставляет

declare 
maxval number(10); 
begin 
    select max(ID) into maxval from XTABLE; 
maxval := maxval+1; 
execute immediate 'DROP SEQUENCE XTABLE_SEQUENCE'; 
execute immediate 'CREATE SEQUENCE XTABLE_SEQUENCE START WITH '|| maxval+50 ||' INCREMENT BY 1'; 
end; 

Вот триггер заявление:

create or replace TRIGGER xtable_sequence_tr 
BEFORE INSERT ON xtable FOR EACH ROW 
WHEN (NEW.id IS NULL) 
BEGIN 
SELECT xtable_sequence.NEXTVAL INTO :NEW.id FROM DUAL; 
END; 

Или что такое правильный способ реализовать автоинкремент в Oracle, чтобы избежать проблемы, с которой я столкнулся? В какой-то момент я запускаю уникальное нарушение ограничения ключа на первичном ключе из-за того, что (я не знаю, по какой причине) максимальный id в таблице оказывается больше, чем последовательность .nextval, используемый в триггере. Что вызывает это и как его исправить?

+0

Что произойдет, если вы воссоздаете последовательность, но с 'nocache', а не' cache 100'? Кроме того, ваша база данных является базой данных RAC? – Boneist

+0

Вы упомянули триггеры. Покажите нам их содержание, пожалуйста. А также операторы sql, сгенерированные спящим, а также –

+0

Вы написали 'last_number своей последовательности: 78400, максимальный id в xtable равен 78308, но следующий следующий код равен 78304.' Но последовательность Oracle не может отменить значение nextval. Вы изменили его вручную? – AlexSmet

ответ

1

Чтобы быть честным, этот пост является довольно запутанным сам по себе.

Вы утверждаете, что

"Для моего стола xtable, LAST_NUMBER его последовательность является 78400, максимальный идентификатор в xtable является 78308, но NEXTVAL Последовательность является 78304."

  1. Что он говорит мне, если имеет порядковый номер последнего, как 78400, было 100 последовательностей, которые были кэшируются в памяти и которые должны быть запущены в 78300. Once 100 последовательностей кэшируются они могут быть только используется, пока сервер не перезагружается, и они изменяют последнее значение последовательности, чтобы показать 78400 в вашем случае, но это не значит, что это то, сколько последовательностей уже было использовано, которые являются просто последовательностями, которые кэшируются в памяти, которые будут использоваться следующей вставкой , если база данных не будет перезапущена в этом случае, вы потеряете те порядковые номера, которые были кэшированы. Кэш последовательности BTW используется для разных сеансов.

  2. «но NEXTVAL последовательности, не изменилась» Опять вы предполагая, что это последнее значение последовательности такой же, как sequence.nextval это не так. Когда вы запрашиваете представление dba_sequences и смотрите столбец Last_NUMBER, оно представляет последнее значение CACHED, а не последнее значение, генерируемое sequence.nextval или используемое в таблице.

Чтобы быть честным, это не должно прикладывать больших усилий.

A. Проверяйте каждый раз, когда вы вставляете строку, вы должны использовать последовательность вместо запуска с помощью процедур или триггеров, а затем возвращаться к последовательностям, не смешивать и не сопоставлять.(Помните, что один из обратных путей использования прямых последовательностей в вставке - это порядок не гарантируется, так как могут быть такие записи, как 1, 2, 3 для id, а затем может быть 10 причин, по которым сервер был перезапущен, и вы потеряли неиспользуемое кешированное значение для последовательностей , если вы действительно всегда хотите заказать, чем использовать последовательность, а не использовать процедуру или другие средства).

B. Вместо того, чтобы сначала запрашивать максимальный идентификатор в таблице, а затем отбрасывать последовательность, а затем снова воссоздавать.

Оставьте последовательность сначала, затем получите максимальное значение из таблицы, а затем создайте последовательность с этой точки вперед. Это избавит вас от потери следа последовательности, которая могла быть использована уже грязной транзакцией из других сеансов, которые, возможно, были исправлены правильно, когда вы делали запрос, чтобы найти максимальный id на таблице ... но он по-прежнему небезопасен.

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

select LAST_NUMBER from dba_sequences where sequence_name='YOUR_SEQUENCE_NAME' 

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

+0

Что я сделал, я создал новые последовательности с начальным номером как max (id) + 1000. Это временно решило проблему, тогда мой webapp снова начал показывать сообщения об ошибках из-за нарушения уникальных ограничений в столбцах первичного ключа (Как видно на сервере журнал). Когда я проверяю последовательность.nextval, она снова меньше max (id) в связанной таблице. – bkn

0

Я понял условие, в котором я получал эту проблему. Дело в том, что, когда я загружал десятки тысяч записей, например, выполнил файл, содержащий 250000 запросов на вставку, кто-то попытается вставить записи (через мой webapp) одновременно. Вероятно, проблема возникла, когда два запроса на вставку, которые будут исполняться одновременно.

+0

У меня такая же проблема только в том, что пользователи только обновляют таблицы и не вставляют записи. И я нашел последнюю последовательность шагов за максимальным идентификатором по 20-разрядным записям в точке. И я пытаюсь выяснить, как обновление пользователей вызывает такой проблема. Но в моем случае процедура удаляет и добавляет записи, но все равно последовательность должна получать следующее значение при вставке. – Evangelos

+0

Это сложно, я все еще получаю ту же проблему и до сих пор не понял причину. На этот раз произошло то, что идентификаторы 1433 и 1434 уже вставлены, затем было выбрано «уникальное ограничение», потому что CURRVAL последовательности был 1433, но должен был быть 1434, так что при следующем вызове NEXTVAL это было бы 1435 , – bkn