Хранимые процедуры и стандартное обновление 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. Проверьте также, что он заблокирован на уровне строк.