Хранимые процедуры и стандартное обновление select, избегайте блокировок

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

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

Запросы, которые я выполняю:

select counter 
from dba.counter_list 
where table_name = :TableName

update dba.counter_list 
set counter = :NewCounter 
where table_name = :TableName

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

2 ответа

Решение

Предположения:

  • вы используете Sybase ASE
  • ваш select возвращает одно значение для counter
  • ты можешь хотеть старого counter значение для какой-либо цели, кроме выполнения обновления

Рассмотрим следующее update заявление, которое должно устранить любые условия гонки, которые могут возникнуть с несколькими пользователями, управляющими select/update логика одновременно:

declare @counter int            -- change to the appropriate datatype

update  dba.counter_list
set     @counter = counter,     -- grab current value
        counter  = :NewCounter  -- set to new value
where   table_name = :TableName

select  @counter                -- send previous counter value to client
  • update получает эксклюзивную блокировку на нужную строку (или страницу / таблицу в зависимости от конструкции таблицы и схемы блокировки)
  • с эксклюзивной блокировкой вы можете получить текущее значение и установить новое значение с помощью одного оператора

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

  • если кэш операторов отключен, пакет SQL необходимо будет компилировать каждый раз, когда он передается на сервер данных.
  • если кэш операторов включен и вы отправляете этот пакет SQL на регулярной основе, то есть вероятность, что предыдущий план запросов все еще находится в кэше операторов / процедур, что устраняет (дорогостоящий) этап компиляции
  • если копия предыдущего сохраненного плана proc (запроса) не находится в кеше процедуры, то при загрузке плана (proc) запроса в процедуру cahe вам потребуется (дорогостоящий) шаг компиляции
  • хранимый процесс, как правило, легче заменить в случае синтаксиса / логики / проблемы с производительностью (в отличие от редактирования и, возможно, компиляции интерфейсного приложения)
  • ... добавить ваш (наименьший) любимый аргумент для пакета SQL против сохраненного proc (против подготовленного оператора?) против??? ...

Доступ к таблице counter_list осуществляется несколькими клиентами одновременно?

Для OLTP рекомендуется вызывать хранимую процедуру, которая будет выполнять логику обновления в одной транзакции.

Убедитесь, что таблица dba.counter_list имеет индекс для столбца table_name. Проверьте также, что он заблокирован на уровне строк.

Другие вопросы по тегам