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

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

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

Я запускаю следующие запросы:

select counter 
from dba.counter_list 
where table_name = :TableName

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

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


person AM AM    schedule 26.09.2017    source источник
comment
Пожалуйста, опубликуйте свой существующий код и объясните свою точную проблему с замками.   -  person PM 77-1    schedule 26.09.2017
comment
@ PM77-1 Я сделал, спасибо   -  person AM AM    schedule 26.09.2017
comment
Блокировки в значительной степени зависят от поставщика, поэтому добавьте тег, чтобы указать, используете ли вы mysql, postgresql, sql-server, oracle или db2, или что-то другое.   -  person marc_s    schedule 26.09.2017
comment
@marc_s это SQL в сочетании с Delphi.   -  person AM AM    schedule 26.09.2017
comment
SQL — это не база данных, а язык запросов. Какую конкретную СУБД вы используете?? Оракул? Майскл? Постгрескл? Жар-птица? Что-то другое?   -  person marc_s    schedule 26.09.2017
comment
@marc_s ты прав, извини. Я использую Сибэйс.   -  person AM AM    schedule 26.09.2017
comment
Существует (по крайней мере) 4 различных продукта РСУБД под названием «Sybase»; какой продукт вы используете? АСЭ? SQLAnywhere? IQ? Преимущество?   -  person markp-fuso    schedule 26.09.2017
comment
Помещение их в одну транзакцию повлияет на блокировку. Я не знаю, будет ли помещение их в хранимую процедуру иметь большой эффект.   -  person Gordon Linoff    schedule 26.09.2017


Ответы (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 или вызов хранимой процедуры, решать вам и вашему администратору баз данных...

  • если кеш операторов отключен, пакет SQL необходимо будет компилировать каждый раз, когда он отправляется на сервер данных.
  • если кеш операторов включен, и вы отправляете этот пакет SQL на регулярной основе, есть вероятность, что предыдущий план запроса все еще находится в кеше операторов/процедур, что устраняет (дорогостоящий) этап компиляции.
  • если копия предыдущего хранимого плана обработки (запроса) отсутствует в кеше процедур, вам придется выполнить (дорогостоящий) этап компиляции при загрузке плана запроса (процедуры) в кеш процедур.
  • хранимую процедуру обычно легче заменить в случае проблем с синтаксисом/логикой/производительностью (в отличие от редактирования и, возможно, компиляции внешнего приложения)
  • ... добавьте свой (наименее) любимый аргумент для пакета SQL по сравнению с хранимой процедурой (по сравнению с подготовленным оператором?) по сравнению с ??? ...
person markp-fuso    schedule 26.09.2017
comment
Большое спасибо за помощь, очень красиво изложено и объяснено! - person AM AM; 26.09.2017

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

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

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

person Remi sap    schedule 26.09.2017