Oracle хранимой процедуры потокобезопасны? - PullRequest
4 голосов
/ 01 июня 2011

Псевдокод:

  1. начать хранимую процедуру

  2. commit

  3. проверить столбец значений1 строки a // шаг 1

  4. обновить столбец 1 строки a // шаг 2

  5. commit

  6. конец хранимой процедуры

Безопасен ли этот поток sp?

edit:

Declare
  tag_rec prep_tag%ROWTYPE;
begin

  COMMIT; 

  SELECT * INTO tag_rec 
  FROM PREP_TAG 
  WHERE project = 'a' and categoryId = 'b'; 

  if tag_rec.locked = 'No' then

    UPDATE prep_tag 
    SET locked = 'Yes' 
    WHERE TAG_NUMBER = tag_rec.TAG_NUMBER;

  end if;

  COMMIT; 

end;

Безопасен ли этот поток sp?Возможно ли, что поток A проверил tag_rec.locked = 'Нет', тогда он собирается обновить его.Но прежде чем он это сделает, поток B пробирается внутрь и также видит tag_rec.locked = 'No'?

Ответы [ 3 ]

7 голосов
/ 01 июня 2011

Короткий ответ на ваш вопрос - нет, это не безопасно. Может пройти какой-то другой сеанс и обновить prep_tag между вашим SELECT и вашими операторами UPDATE.

Длинный ответ заключается в том, что вы делаете это неправильно. Похоже, вы хотите обновить заблокированное поле для этих записей. Вы могли бы просто сделать:

UPDATE prep_tag SET locked = 'Yes' 
 WHERE project = 'a' 
   AND categoryId = 'b'
   AND locked = 'No'

Одно утверждение, и оно гарантированно будет атомарным.

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

4 голосов
/ 01 июня 2011

Oracle не блокирует SELECT (если нет предложения FOR UPDATE), поэтому существует вероятность, что строка будет обновлена ​​между SELECT и UPDATE.

Но более вероятный сценарий состоит в том, что строка была бы обновлена ​​до выбора и не была зафиксирована SELECT покажет текущее зафиксированное состояние. Тогда ОБНОВЛЕНИЕ придет и будет ждать на замке.

Предполагая, что вы не хотите блокировать сеанс, посмотрите SELECT ... FOR NOWAIT UPDATE и разберитесь с исключением. Альтернативой является SERIALIZABLE уровень изоляции. Это в основном приведет к ошибке «ORA-08177 не может сериализовать доступ для этой транзакции», если будет предпринята попытка изменить данные, которые не были текущими в начале транзакции.

4 голосов
/ 01 июня 2011

Вам не нужно проверять свой собственный механизм проверки.Oracle уже предоставляет эту функциональность с помощью синтаксиса SELECT ... FOR UPDATE.WAIT | NOWAIT управляет поведением, если выбранная строка заблокирована (подождите или сразу же произойдет сбой). Узнайте больше .(В 11g Oracle выставил предложение SKIP ROWS , которое позволяет нам реализовать наш собственный механизм организации очередей.)

Если вам нужен более сложный процесс блокировки, Oracle позволяет нам создавать свои собственные с пакет DBMS_LOCK .Тем не менее, привилегии на этот пакет не предоставляются никому по умолчанию;это потому, что создание пользовательских процедур блокировки сложно.

...