在我的.NET Web应用程序中,我有一个例程,它分为两部分。大多数情况下,例程的两个部分都是一个接一个地调用,
var result = Method1(someParams);
var finalResult = Method2(result);
它们被分为两个,因为一个可以而且有时被调用而不调用另一个。这两种方法都在内部查询表Table1
中的数据。由于上面两种方法的参数不同,它们运行的选择查询也不同,但是我想要锁定将由这两种方法中的任何一种选择的行,以便其他方法在之前无法选择它。首先查询它的人已经完成了。由于选择的数据应该在之后更新,因此select查询使用UPDLOCK
关键字,但如上所述,其中两个方法具有不同的参数,因此我为实现最佳结果所做的是:
Method1
执行此查询
SELECT Id FROM Table1 WHERE Column1 = @Param1 AND Column2 = @Param2
然后它使用选定的Id
执行以下查询以获取所有列。
SELECT Id, Column1, Column2, Column3, Column4
FROM Table1 WITH ( UPDLOCK, INDEX ( PK_Table1 ) )
WHERE Id = @IdParam
Method2
仅执行第二个查询(因为Id从外部传递给它)。因此,只要同时调用Method1
和Method2
(对于同一记录),就会在更新数据之前等待另一个,因为他们必须获取UPDLOCK
行。
我还在查询中包含INDEX(PK_Table1) --(Primary Key)
,因为我认为数据库由于某种原因正在切换索引。
我偶尔遇到的问题是,当这些方法同时被调用4次或更多次时(对于同一行),锁定机制无法正常工作。我看到的结果直接暗示记录在被选中时没有被锁定。我在这些情况下做的只是改变包含上述查询的过程(没有修改查询,这可能只是强制重新编译它)。我可以看到改变帮助,因为我编写了一个测试,检查上面提到的机制是否正常工作。在我检测到存在问题之后,在我改变程序之前,我运行测试,结果是错误的,如果锁定工作正常则不应该发生,在改变这两个程序后,我再次运行测试,一切正常。
此案例在1-2个月内出现一次,但在检测到并修复之前确实会造成一些损害。它已经发生了4次。第3次发生时,我在INDEX(PK_Table1)
条款中添加了WITH
,我确信这是一个修复,但它又发生了。
答案 0 :(得分:0)
(更新:我的答案不适用,因为不同交易中的UPDLOCK确实应该像OP期望的那样工作。)
UPDLOCK不会阻止其他会话读取,只会阻止更新。使用提示或隔离级别似乎无法解决这个问题。
您可以通过实际使用其当前值更新行来生成锁定,并在提交事务之前使用新值再次更新,从而完成您尝试的操作。但是,可能有更安全的方法去做你想要的目标。