如何重现“由于数据移动,无法使用NOLOCK继续扫描”


10

我偶尔会遇到NOLOCK一些大型作业“确实由于数据移动而无法继续扫描”的情况,这些作业确实存在WITH (NOLOCK)于选择查询中。

我知道这与尝试在发生页面拆分时选择数据有关,这导致数据不再位于应有的位置-我认为这就是我的环境中发生的事情。

我将如何重现?

我试图做一个短期的变通办法来捕获错误并在发生这种情况时重试,但是如果无法重现它,我将无法对其进行测试。是否有合理可靠的方法引起这种情况?

当发生这种情况时,再次执行查询会成功-因此,我对实际数据或数据库永久损坏没有任何担心。查询中的某些表(以及它们的索引)经常被删除,重新创建和重新填充,因此我假设它与此相关。

删除NOLOCK是我要解决的长期问题。首先NOLOCK放在这里的原因是,查询是如此糟糕,以至于它们陷入日常事务的僵局中,因此NOLOCK,用于阻止僵局(工作正常)的创可贴也是如此。因此,在我们可以做一个永久性解​​决方案之前,我需要一个创可贴。

如果我可以用《 Hello World》来复制它,我计划在不到一个小时的时间内将创可贴打入工作。无法进行搜索和替换删除NOLOCK,因为我将再次开始遇到应用死锁,这对我来说比偶尔的失败工作更糟糕。

使用读取提交的快照隔离是一种很好的可能性-我将不得不与我们的数据库团队合作以获取有关该快照的更多详细信息。问题的一部分是,我们没有SQL Server专家来处理此类问题,而且我对隔离级别的理解不充分,无法立即进行更改。


1
您是否考虑过简单地NOLOCK从这些工作中撤职?如果这些查询的结果正确无误,则 601应该是您最少的担心。保罗怀特(Paul White)展示了一个特别可怕的例子,读取数据在这里不可能做到。
亚伦·伯特兰

3
您可以在作业中设置DEADLOCK_PRIORITYLOW,这样,如果出现死锁,作业将失败,而不是应用程序。之后,您可以研究僵局并找出发生这种僵局的原因,并解决该问题。这可能是非常简单的修复,例如交换两个语句的顺序。不管问题是什么,NOLOCK不是解决办法,所以停止试图迫使它只是因为这是最容易的。
亚伦·伯特兰

@AaronBertrand谢谢,不知道DEADLOCK_PRIORITY-我会调查一下。我们尝试跟踪死锁,但是死锁是在各个看似随机的时间发生的,每天仅发生一次或两次,并且无法按需重现-我们的计划作业每小时运行数万个查询,而我们的应用程序执行数百次仅在加载页面或保存内容时的查询数量,并且我们还没有找到死锁中涉及哪一侧的查询。我无意永远把NOLOCK留在那儿,这就是为什么我们在研究更好的长期解决方案。
wookie23

1
您提到您很难找到僵局。假设您使用的是2008 R2,则可以在此处查看:sqlservercentral.com/articles/deadlock/65658 Jonathan Kehayias讨论了从环形缓冲区获取死锁信息的问题。
肯尼斯·费舍尔

答案和评论很好地解决了潜在的问题,但是您仍然想找到一种方法来将其重现为智力活动吗?
James L

Answers:


8

由于NOLOCK问题的一种潜在“创可贴”是停止使用NOLOCK并开始使用READ_COMMITTED_SNAPSHOT隔离,因此我想将您引到Kendra Little 的博客文章:http ://www.brentozar.com:实现快照或已提交读操作。 《 SQL Server中的快照隔离:指南》

Kendra通过使用READ_COMMITTED_SNAPSHOT隔离级别,提供了很多有关收益和风险的详细信息。

  1. 该隔离级别成为数据库代码的默认隔离级别。
  2. 您只需在数据库中只有一个用户即可更改READ_COMMITTED_SNAPSHOT隔离级别。
  3. 即使您使用READ_COMMITTED_SNAPSHOT隔离,您仍将需要删除NOLOCK提示,因为它们会覆盖默认值。
  4. 您的某些代码可能存在需要解决的问题。

几年前,我们在严重遭受阻塞的数据库上实现了READ_COMMITTED_SNAPSHOT隔离。但是,一旦我们更改了隔离级别,我们就开始在几个关键领域陷入僵局

为什么会这样呢?因为先前的隔离级别导致了严重的阻塞,所以代码“永远”不会达到死锁的程度。但是,使用READ_COMMITTED_SNAPSHOT隔离,查询可以继续前进。但是,一定比例的不再等待的事务开始陷入僵局。

幸运的是,通过确定死锁点并调整几个表上的索引以使列顺序更合理,我们的情况得以快速解决。这大大减少了我们的锁定问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.