Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Sql Server 2012存在锁定问题(UPDLOCK)_Sql Server_Stored Procedures_Sql Server 2012_Locking - Fatal编程技术网

Sql server Sql Server 2012存在锁定问题(UPDLOCK)

Sql server Sql Server 2012存在锁定问题(UPDLOCK),sql-server,stored-procedures,sql-server-2012,locking,Sql Server,Stored Procedures,Sql Server 2012,Locking,在我的.NETWeb应用程序中,我有一个分为两部分的例程。大多数时候,例行程序的两个部分都会被一个接一个地调用 var result = Method1(someParams); var finalResult = Method2(result); 它们分为两个,因为一个可以被调用,有时被调用而不调用另一个。这两种方法都从表Table1内部查询数据。由于上述两个方法的参数不同,因此它们运行的select查询也不同,但我想锁定将由这两个方法中的任何一个选择的行,以便在第一个查询它的方法完成之前,

在我的.NETWeb应用程序中,我有一个分为两部分的例程。大多数时候,例行程序的两个部分都会被一个接一个地调用

var result = Method1(someParams);
var finalResult = Method2(result);
它们分为两个,因为一个可以被调用,有时被调用而不调用另一个。这两种方法都从表
Table1
内部查询数据。由于上述两个方法的参数不同,因此它们运行的select查询也不同,但我想锁定将由这两个方法中的任何一个选择的行,以便在第一个查询它的方法完成之前,另一个方法将无法选择它。由于选择的数据应在之后更新,因此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
数据之前一样

我还将
索引(PK_Table1)-(主键)
包含在查询中,因为我认为数据库出于某种原因正在切换索引

我偶尔遇到的问题是,当这些方法同时被调用4次或更多次(对于同一行)时,锁定机制无法正常工作。我看到的结果直接表明,选择时记录没有被锁定。在这些情况下,我所做的只是修改包含上述查询的过程(不修改查询,这可能只是强制重新编译查询)。我可以看出,更改有帮助,因为我编写了一个测试,检查上述机制是否正确工作。在我检测到有问题之后,在我改变程序之前,我运行了一个测试,该测试产生了错误的结果,如果锁定工作正常,则不应该发生。在改变这两个程序之后,我再次运行测试,一切正常

这种情况每1-2个月出现一次,但在被发现和修复之前确实造成了一些损害。已经发生过4次了。第三次发生时,我在
WITH
子句中添加了
索引(PK_Table1)
,我确信这是一个修复,但又发生了。

(更新:我的答案不适用,因为不同事务中的UPDLOCK确实应该按照OP的预期工作。)

UPDLOCK不会阻止其他会话读取,只会阻止更新。似乎实际上没有办法使用提示或隔离级别来解决这个问题


您可以通过实际使用行的当前值更新行以生成锁,并在提交事务之前使用新值再次更新来完成所尝试的操作。但可能有更安全的方法来实现您的目标。

据我所知,如果在同一行请求两个UpdLock,一次一个将获得它。当第一个SELECT将实际选择具有UPDLOCK的行时,另一个具有UPDLOCK的SELECT将无法在提交第一个事务之前读取或获取同一行上的锁。您的意思是UDPLOCK不会阻止其他会话读取,这是正确的,但如果其他会话也在使用UPDLOCK读取,它会阻止其他会话读取。所以在我的例子中,两个查询都是用UPDLOCK读取数据。我非常尴尬……我以为你陷入了我有时会做的那种证据曲解。您很可能遇到了一个罕见的SQL Server错误。事务是否在这两个存储过程中打开和提交?是的,这些请求加上随后的更新都在更新后提交的同一SQL事务作用域中运行。外部两个方法不是在同一个SQL事务中运行的(当一个接一个地运行时),但两个方法(Method1和Method2)的内部都是。我有兴趣尝试一下,看看是否可以重现这一点。但我不得不怀疑,与其说它是SQL Server锁定错误,不如说它是在没有事务的地方调用SP。我从你上次对我的错误回答的回复中得知,你正在用你的.net代码打开并提交交易?如果是这样,您是否考虑将事务管理移到SP代码中?我是否可以询问您所处的SQL 2012版本,数据库设置为什么兼容级别,数据库上是否启用了readcommittedsnapshot和/或快照隔离,事务使用什么隔离级别?是的,应用程序正在.NET环境中运行。确切地说,它是ASP.NETMVC4。那些sql过程只是从Method1和Method2运行的,没有人关心它们的存在,我非常怀疑问题在于打开/提交事务。(在.NET端)这是@@Version字符串--Microsoft SQL Server 2012(SP3-CU5)(KB3180915)-11.0.6544.0(X64)2016年8月29日14:00:09版权所有(c)Microsoft Corporation Enterprise Edition:Windows NT 6.3(Build 9600:)上基于核心的许可(64位)(虚拟机监控程序)兼容性级别为110,已启用读提交快照。对于上面的查询,我没有指定自定义隔离级别,因此它应该是默认隔离级别。我只访问SP1,但我使用两个SP在20个线程中运行20k次,每5秒重新编译一次,sys.dm_tran_locks中会话的锁行数在每次udplock选择后显示预期的4行(然后更新行并提交)。而且等待任务始终为~40,因此锁定肯定有效。(续)