我有一个现有的存储过程SP1,可以从表中进行简单的选择。它被用于多个地方。
现在有一个新代码在一个可序列化的事务中使用此SP1以及更新语句。我看到死锁,其中两个事务能够在同一组行上获取读锁定,现在想要将该锁定转换为更新。
一种可能的解决方案是使此SP1在读提交隔离级别执行。 但我认为这不是正确的解决方法,因为可能会丢失更新。另一个解决方案是在SP1的select语句中提示UPDLOCK
。这将解决死锁,因为任何事务获取UPDLOCK只会继续。另一个事务必须等待提交。
现在向此SP1添加UPDLOCK
不必要地为其他调用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();
}
答案 0 :(得分:1)
如果SP2之后对SP1的调用是原子的,则它们应该在T-SQL中组合。 或者丢失c#事务。您通过往返不必要地延长了交易。
另外,为什么UPUPOCK在SP1UPDLOCK而不是SP1?我不明白为什么。如果问题是锁定提示,请不要使用它们。如果某些东西是可序列化的(为什么?)那么再次,使它成为一个原子调用
请注意,默认情况下是READ COMMITTED
最后,你的意思是“信号量”没有锁定?使用sp_getapplock将控制代码流,而不使用数据上的锁