Можете ли вы заблокировать последовательность Oracle?

#sql #oracle #sequence

#sql #Oracle #последовательность

Вопрос:

Возможно ли заблокировать последовательность Oracle, чтобы любой сеанс, пытающийся использовать nextval на нем, блокировался, пока я не закончу со своим скриптом?

Я объясню, что я делаю, на случай, если есть другой способ. Я готовлю схему для выполнения двунаправленной репликации с потоками. Я хочу убедиться, что все последовательности первичных ключей выдают уникальные значения. Я делаю это, увеличивая последовательность на 1, пока последняя цифра не будет равна 1, а затем изменяю приращение на 100. На другом сервере я делаю то же самое, пока последняя цифра не будет равна 2. Таким образом, сервер 1 всегда выдает первичные ключи XXXXX01, а сервер 2 XXXXX02.

Проблема в том, что это база данных 24×7, и я не могу остановить все действия, пока я настраиваю последовательности. Если я смогу получить эксклюзивную блокировку на короткое время, я смогу сделать это надежно.

Комментарии:

1. Вы можете принять текущее значение последовательности за максимальное значение.

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

Ответ №1:

Самое простое возможное решение (на мой взгляд) — использовать нечетные числа для сервера 1 и четные числа для сервера 2. Это также устраняет необходимость в сериализации.

 create sequence server1_seq increment by 2 start with 1;
create sequence server2_seq increment by 2 start with 2;
  

Это привело бы к появлению ряда значений типа:

 Server 1  Server 2
--------  --------
   1          2
   3          4
   5          6 
   7          8
   9         10
  

Это решение может быть дополнительно расширено для обработки более двух серверов за счет использования больших приращений (и разных начальных значений для каждого сервера).

Сказав это, НЕ используйте этот подход, если вы собираетесь со временем добавить больше серверов. Вам пришлось бы перевести все базы данных в автономный режим и перестроить таблицы с нуля.

Комментарии:

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

2. @JOTN, ах, извините, я неправильно понял проблему.

Ответ №2:

Нет, вы не можете заблокировать последовательность. Вы могли бы попытаться воссоздать последовательности в требуемом состоянии. На короткое время это вызовет проблему.

Комментарии:

1. Спасибо. Я думаю, просто попробуйте сделать это в спокойное время и, надеюсь, установите последовательность до того, как она появится в другом сеансе. Если я не получу их все, я всегда могу запустить скрипт снова.

Ответ №3:

Лично мне нравится идея использования отдельных неперекрывающихся последовательностей, как предложил Роннис.

Другой вариант, который следует рассмотреть, — это составной первичный ключ.

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

  2. Если вы не можете добавить столбец, вы могли бы вместо этого изменить тип данных столбца на VARCHAR2 и установить его как составной; например, на сервере 1 вы бы объединили ‘1-‘ со значением последовательности, например, ‘1-103450’ поэтому не конфликтовал бы с ‘2-103450’, созданным на сервере 2.

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

Ответ №4:

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

 REVOKE SELECT ON mysequence FROM username;
  

Примечание: это не блокировка как таковая; вместо ожидания они получат сообщение об ошибке Oracle (я думаю, неверный идентификатор).

Ответ №5:

Кажется, вы действительно можете заблокировать последовательность.

 SELECT SEQ_NAME.nextval FROM dual FOR UPDATE [NOWAIT];
  

Протестировано на Oracle 11 XE. Также взгляните на https://www.experts-exchange.com/questions/20181432/lock-wait-on-sequence.html и https://geraldonit.com/oracle/database/oracle-database-locktypes /.