Параллелизм функции Oracle - PullRequest
       20

Параллелизм функции Oracle

3 голосов
/ 16 декабря 2008

В настоящее время у меня есть INSERT TRIGGER, который в Oracle 10g выполняет пользовательскую функцию, генерирующую необычный буквенно-цифровой код, который используется как часть вставки.

Мне действительно нужно убедиться, что функция (или даже триггер) является поточно-ориентированной, поэтому, если два пользователя активируют триггер одновременно, функция, используемая в триггере, НЕ возвращает один и тот же код для обоих пользователей.

Поток в триггере выглядит следующим образом:

START

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

END

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

Я подумал о двух основных способах сделать это:

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

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

Моя идея не идеальна, но она должна работать, однако я хотел бы услышать от любого, кто может иметь лучшие идеи, что это!

Большое спасибо за предоставленную помощь.

Ура, Mark

Ответы [ 3 ]

5 голосов
/ 16 декабря 2008

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

Ключ в том, что каждый вызов вашей "пользовательской функции" должен возвращать уникальный код.

Это означает, что НЕ используется системная дата / время, но что-то еще для обеспечения уникальности.

Я рекомендую это:

select sys_guid() from dual;

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

Просто ПОЖАЛУЙСТА, не пытайтесь обновить другую таблицу с этим значением, иначе вам придется иметь дело с изменяющимися таблицами и тому подобным.

Редактировать: Очевидно, что, как уже упоминалось парой, использование последовательности в триггере для заполнения вашей функции является еще одним хорошим предложением, так как Oracle обеспечивает уникальность. Однако его использование в качестве начального числа может привести к предсказуемому результату, поэтому будьте осторожны, если «пользовательская функция» - это сброс пароля или что-то в этом роде.

1 голос
/ 16 декабря 2008

Одним из решений является использование последовательности Oracle для подачи в ваш пользовательский код, который генерирует уникальную строку. Oracle предоставляет последовательности именно по этой причине - поэтому методы, генерирующие уникальные идентификаторы, являются поточно-ориентированными. Смотрите здесь для документации по Oracle 9i (версия, которую я использую).

1 голос
/ 16 декабря 2008

"Вам вообще не нужно знать, что это такое, это просто код, который генерирует функция" Тогда это должно быть основано на времени, потому что что-либо еще, и мы БУДЕМ знать, чтобы иметь возможность дать соответствующий ответ. Не уверен, будет ли у вас пропускная способность. Вы можете рассматривать DBMS_LOCK.REQUEST как 1a, DBMS_LOCK.SLEEP как 2a и DBMS_LOCK.RELEASE как 2b. Это может гарантировать, что каждая блокировка удерживается в течение одной секунды, так что в одну секунду может произойти только одна вставка.

Если Oracle основан на последовательности, вы не получите ту же самую последовательность дважды

Если это зависит от состояния сеанса / пакета (например, увеличение в течение сеанса), тогда сеанс может иметь только одну вставку за раз (хотя это может быть вставка из нескольких строк ... select или даже из нескольких таблица вставка).

Если это зависит от состояния базы данных (т. Е. Функция выполняет запросы), вам нужно думать о транзакциях, а не об операторах. Вы все еще можете использовать DBMS_LOCK, но вам нужно будет снять блокировку вручную после фиксации, чтобы гарантировать, что сеанс ожидания действительно ожидает, пока новые данные не будут зафиксированы и видимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...