Как намекнуть блокировку обновления без дублирования кода хранимой процедуры - PullRequest
0 голосов
/ 08 августа 2011

У меня есть существующая хранимая процедура SP1, которую просто выбрать из таблицы.Он используется в нескольких местах.

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

Одним из возможных решений является выполнение этого SP1 на уровне изоляции с фиксацией чтения. Но я думаю, что это не правильное решение, , поскольку могут быть потеряны обновления.Другим решением является подсказка UPDLOCK в операторе выбора SP1.Это разрешит взаимоблокировку, так как любая транзакция обнаружит, что UPDLOCK будет только продолжаться.Другой транзакции придется подождать, пока это будет зафиксировано.

Теперь добавление UPDLOCK к этому SP1 излишне добавляет эти издержки для других мест, которые вызывают SP1, но не хотят UPDLOCK.Поэтому можно подумать, что нужно продублировать этот SP1 и получить новый SP1UPDLOCK, который совпадает с SP1, но с UPDLOCK.Я не хочу этого дублирования.Таким образом, есть ли способ, которым вызывающая сторона может намекнуть, что любой возврат SP1 должен быть взят с UPDLOCK.

Любой другой лучший способ решить этот тип проблемы.

Я использую SQL Server 2008, C #, .NET 4.

Пример кода

CREATE PROCEDURE SP1
    @SomeId int
AS
BEGIN
    Select Foo From Bar Where SomeOne = @SomeId
END

CREATE PROCEDURE SP1UPDLOCK
    @SomeId int
AS
BEGIN
    Select Foo From Bar (UPDLOCK) Where SomeOne = @SomeId
END

CREATE PROCEDURE SP2
    @Foo int
    @SomeId int
AS
BEGIN
    Update Bar
    Set Foo = @foo
    Where SomeOne = @someId
End

Код C #

Using(Transaction t = new Transaction())
{
    result = SP1(someId);
    // some logic here
    if(somecond == true)
    {
        SP2(fooVal, someId);
    }

    t.Commit();
}

1 Ответ

1 голос
/ 08 августа 2011

Если вызовы SP1, следующие за SP2, являются атомарными, они должны быть объединены в T-SQL. Или потерять транзакцию c #. Вы продлеваете транзакцию без необходимости с помощью туда и обратно.

Кроме того, почему UPDLOCK включен в SP1UPDLOCK, но не для SP1? Я не понимаю почему. Если проблема заключается в подсказках блокировки, не используйте их. Если что-то сериализуемо (почему?), То снова сделайте это единым атомарным вызовом

Обратите внимание, что по умолчанию READ COMMITTED в любом случае

Наконец, вы имеете в виду "семафор", а не блокировка? Использование sp_getapplock будет управлять потоком кода без использования блокировок данных

...