Sql server NOLOCK会导致DISTINCT失败吗?

Sql server NOLOCK会导致DISTINCT失败吗?,sql-server,Sql Server,免责声明:这不是关于NOLOCK问题的一般性问题(因此不是的副本);这是一个关于NOLOCK和DISTINCT如何交互以更好地理解SQLServer内部工作的具体问题 尽管看起来很奇怪,但在我看来,NOLOCK可能会导致DISTINCT在特定情况下失败。以下是一个例子: INSERT INTO TableA (ID) SELECT DISTINCT ID FROM TableB WITH (NOLOCK) 上面的示例偶尔会产生PK冲突。以下是其他相关事实: 表A的PK是ID 表B的PK为ID

免责声明:这不是关于NOLOCK问题的一般性问题(因此不是的副本);这是一个关于NOLOCK和DISTINCT如何交互以更好地理解SQLServer内部工作的具体问题

尽管看起来很奇怪,但在我看来,NOLOCK可能会导致DISTINCT在特定情况下失败。以下是一个例子:

INSERT INTO TableA (ID)
SELECT DISTINCT ID
FROM TableB WITH (NOLOCK)
上面的示例偶尔会产生PK冲突。以下是其他相关事实:

  • 表A的PK是ID
  • 表B的PK为ID
  • 开始时,表A为空
  • 在这段时间里,没有其他东西在向TableA写信
  • 在运行上述程序时,TableB会发生更新
我的工作原理是1)TableB上的更新与NOLOCK的使用相结合会导致重复数据,2)优化器依赖于这样一个事实,即TableA在我们要区分的同一列上有一个PK,因此不会主动对返回的行执行不同的操作,它只是假设行已经是不同的

有人能证实这一点吗?如果是这样,这是出于设计,还是SQL Server中的一个缺陷

我最初认为,即使是脏读和重复行的可能性,DISTINCT也可以保证清除重复行,但我看到的证据似乎表明并非如此


在SQL Server 2008R2上看到此错误。

确保会发生此错误。引擎足够聪明,知道既然ID是您的主键,它不会浪费资源寻找重复项。然而,您已经引入了可怕的NOLOCK提示。你说在这个过程中表格B正在更新


你在这里几乎可以肯定地感受到的是页面分割带来的NOLOCK的副作用之一。这些页面分割会导致引擎返回重复的行,正如我之前所说的,引擎假设没有重复行,因为您选择的是主键,并且不存在重复行。这不是sql server中的错误,这是另一个原因,因此请停止使用提示。

nolock可能会导致许多问题,最好尽可能避免它。副作用可能包括重复记录和丢失记录。您的体验取决于当前正在读取的对象上发生的突变。另请参阅非关键读取的NOLOCK提示可能与You get await的副本,但是,这是一个更新/插入命令的示例,您希望避免使用NOLOCK。我理解NOLOCK的一般问题(数据准确性、可能重复、可能丢失行),但这个问题是关于NOLOCK导致DISTINCT命令无法执行其任务的可能性。我希望有人知道答案。也就是说,我不仅仅是在寻找如何使这段代码工作,而是想了解SQL Server在这种情况下做了什么以及为什么。就我认为SQL Server应该保证的内容而言,有一种明显的失败会动摇我的世界。虽然我完全同意NOLOCK是一种不好的做法,但我不认为这是一种重复。OP表示他们理解nolock,并想知道为什么会使用该提示出现重复项。我认为你是对的,但你知道任何与此相关的文档吗?事实上,我在SSC的一个论坛上找到了类似的内容。盖尔·肖和我说的差不多。很好的链接,谢谢!当盖尔·肖和保罗·怀特在某件事上插话时,这几乎就把它封住了。我真希望微软在这方面提供一些文档,或者在我心目中更好的是,一篇精心制作、插图完美的Paul White文章。:)我知道我以前读过这方面的文章,我很惊讶。很高兴我能从一些知名人士那里找到关于这个话题的链接。