У меня есть существующая хранимая процедура 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();
}