Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.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 在我的情况下,With(NoLock)提示危险吗?_Sql Server_Deadlock_Nolock - Fatal编程技术网

Sql server 在我的情况下,With(NoLock)提示危险吗?

Sql server 在我的情况下,With(NoLock)提示危险吗?,sql-server,deadlock,nolock,Sql Server,Deadlock,Nolock,我已经阅读和使用withnolock提示很多次了,但我有一个具体案例的问题 在我的例子中,我有一组引用和更新一个数据库的代码。 此代码旨在以单线程方式运行。 几个月前,他们决定在不更改代码的情况下实现多线程。他们的做法是让每个不同的代码处理器管理不同的存储组 例如,processor1负责存储1到20,processor2负责存储21到40,依此类推 一切似乎都很好,直到我们开始陷入僵局。死锁总是在页面上。。。如果锁仅在行上,我们将永远不会得到死锁,因为来自一个处理器的数据从不与来自另一个处理器

我已经阅读和使用withnolock提示很多次了,但我有一个具体案例的问题

在我的例子中,我有一组引用和更新一个数据库的代码。 此代码旨在以单线程方式运行。 几个月前,他们决定在不更改代码的情况下实现多线程。他们的做法是让每个不同的代码处理器管理不同的存储组

例如,processor1负责存储1到20,processor2负责存储21到40,依此类推

一切似乎都很好,直到我们开始陷入僵局。死锁总是在页面上。。。如果锁仅在行上,我们将永远不会得到死锁,因为来自一个处理器的数据从不与来自另一个处理器的数据冲突。基于这一理论,我决定在每一个不需要锁定但尚未投入生产的选择上使用WithNolock提示。。。这让我的死锁在实验室里消失了

一切似乎都很好,很漂亮,直到我的同事拿着一篇文章走到我跟前,把我吓坏了。。。 然后我读到


在我的情况下使用WithNolock提示是否有危险。。。处理器之间的数据不会发生冲突的地方?

是的,如果您收集的数据必须准确,则可能会出现问题-您可能会获取脏数据/不正确数据,然后将其持久化。您是否研究过索引是否可以解决死锁问题?通常,死锁场景可以通过控制数据页的访问模式来解决,该模式由可用索引控制


我喜欢做的是查看死锁图,看看冲突在哪里,然后查看代码中的操作顺序,以及使用哪些索引来访问/修改数据,看看是否可以调整以消除死锁风险。

收回nolock提示并将数据库置于快照隔离级别

上的“读取已提交的快照数据库”选项


有关更多信息,请参阅。但是,请注意,保存tempDB的磁盘在快照隔离中会遇到更高的I/O。

您的select查询似乎是死锁的原因。这就是可能发生的事情。稍后您可能会选择并更新记录。因此,当更新记录时,超过5000个sql server使用锁升级并锁定整个表,而不是锁定行

如果你的程序是-

select .......
--some coding here----
update statement
如果另一个线程在update语句之前使用select语句,则update语句将因共享锁而被阻止,update语句将等待释放共享锁,同时另一个进程发出update语句。第二个进程更新语句将被阻止,因为您应用了共享锁。因此,当两个线程都在等待对方时,就会发生死锁

解决方案-

使用UPDLOCK提示-这将允许共享锁,但不允许更新锁。将select语句转换为-> 使用UPDLOCK和ROWLOCK从mytable中选择* RowLOCK提示将在行级别而不是页面或表级别保持锁定。这将减少死锁

使用快照隔离


注意不要在select语句中与NOLOCK一起使用,因为这将导致未提交数据的脏读,这可能是错误的。

调查快照隔离。它消除了大量的阻塞,并且严格来说比只读访问的read committed更加一致。我的理论是,在这种情况下读取脏数据不应该是一个问题,因为没有处理器接触来自另一个处理器的数据。第一篇文章让我害怕的是缺少行,读了两行,读了同一行的多个版本。这是同一代码,在同一时间运行多次。因此,相同的索引将受到影响。因此,我遇到了很多僵局。大多是一个X锁,最多3个S锁。通常S锁是受害者。缺少行、读取两次和读取多个版本都是脏数据的例子,建议使用RCSI。首先测试,但实际上总是一个胜利。阅读之后,RCSI似乎不会通过这里,因为我们需要修改属于客户的服务器上的DBs。我想我必须回到绘图板,分析死锁中使用的索引。我将与开发人员坐在一起,了解事件和事务的顺序。在我看来,Withnolock是一个可行的解决方案,直到这个线程。我没有尝试UPDLOCK,但是当我尝试ROWLOCK提示时,我仍然看到一些页面锁定发生,这就是我没有继续的原因。理想情况下,ROWLOCK提示可以解决我的所有问题,但不能确定是否会发生行锁定。