Oracle (PL / SQL): является ли ОБНОВЛЕНИЕ ВОЗВРАТА одновременно - PullRequest
5 голосов
/ 28 мая 2010

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

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

Я создаю записи (назовем их элементами), у которых есть ключ (bucket_id, num = counter).

Мне нужно гарантировать, что комбинация bucket_id / num уникальна (поэтому использование последовательности в качестве prikey не решит мою проблему).

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

Мое решение было:

   UPDATE bucket
      SET counter = counter + 1
    WHERE id = param_id
RETURNING counter INTO num_forprikey;

PL / SQL возвращает var_num_forprikey, чтобы можно было создать запись элемента.

Вопрос:

Буду ли я всегда получать уникальный num_forprikey, даже если пользователь одновременно запрашивает новые предметы в корзине?

Ответы [ 4 ]

7 голосов
/ 28 мая 2010

Всегда ли я получу уникальный num_forprikey? даже если пользователь одновременно запрашивает новые предметы в ведре?

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

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

1 голос
/ 30 мая 2010

Вы все еще можете использовать последовательности, просто используйте аналитическую функцию row_number (), чтобы порадовать своих пользователей. Я описал это здесь более подробно: http://rwijk.blogspot.com/2008/01/sequence-within-parent.html

С уважением, Роб.

1 голос
/ 30 мая 2010

Кажется, я вспоминаю эту проблему из-за многолетней работы над базой данных INGRES. В те дни не было никаких последовательностей, поэтому лучшие умы INGRES дня приложили немало усилий, чтобы найти лучшее решение для масштабирования этой проблемы. Мне посчастливилось работать вместе с ними, так что, хотя мой разум ничтожно мал, чем у любого из них, близость = остаточный аффект, и я кое-что сохранил. Это была одна из вещей. Дай посмотреть, смогу ли я вспомнить.

1) for each counter you need row in a work table.
2) each time you need a number
  a) lock the row
  b) update it
  c) get its new value (you use returning for this which I avoid like the plague)
  d) commit the update to release your lock on the row

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

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

Вы должны будете принять тот факт, что ваша масштабируемость резко снизится в этом сценарии. Это связано как минимум с двумя причинами:

1) последовательность update / select / commit делает все возможное, чтобы уменьшить время, в течение которого строка KEY блокируется, но она все еще не равна нулю. Под большой нагрузкой вы будете сериализованы и в конечном итоге будете ограничены.

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

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

Но если ваш клиент этого требует, что вы можете сделать правильно?

Удачи. Я не проверял код на наличие синтаксических ошибок, я оставляю это вам.

create or replace function get_next_key (key_name_p in varchar2) return number is
   pragma autonomous_transaction;
   kev_v number;
begin

   update key_table set key = key + 1 where key_name = key_name_p;

   select key_name into key_name_v from key_name where key_name = key_name_p;

   commit;

   return (key_v);

end;
/
show errors
0 голосов
/ 28 мая 2010

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

http://www.orafaq.com/forum/t/83382/0/ Преимущество для последовательностей (и они могут быть созданы динамически, если вы можете указать nocache и порядок гарантии)

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