NOLOCK会导致DISTINCT失败吗?

Joh*_*nyM 5 sql-server

免责声明:这不是关于NOLOCK问题的一般性问题(因此不是NOLOCK(Sql Server提示)错误做法的重复吗?); 这是一个特定的问题,关于NOLOCK和DISTINCT如何交互以试图更好地理解SQL Server的内部工作.

虽然看起来很奇怪,但在我看来,NOLOCK可能会导致DISTINCT在某种情况下失败.这是一个例子:

INSERT INTO TableA (ID)
SELECT DISTINCT ID
FROM TableB WITH (NOLOCK)
Run Code Online (Sandbox Code Playgroud)

以上示例偶尔会产生PK违规.以下是其他相关事实:

  • TableA的PK是ID
  • TableB的PK是ID
  • 启动时,TableA为空.
  • 在此期间,没有其他任何内容写入TableA.
  • 在上面运行时,TableB会发生更新.

我的工作理论是:1)TableB上的更新与NOLOCK的使用相结合导致重复数据,2)优化器依赖于TableA在同一列上具有PK的事实,我们是DISTINCTing,因此不会t主动对正在返回的行执行DISTINCT操作,它只是假设行已经是不同的.

谁能证实这一点?如果是这样,这是设计,还是SQL Server中的错误?

我原本以为即使有脏读也有重复行的可能性,DISTINCT将是清理重复项的保证,但我看到的证据似乎表明不是这样.

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

Sea*_*nge 5

当然这可能会发生。该引擎足够聪明,知道由于 ID 是您的主键,因此不会浪费资源来寻找重复项。然而,您引入了可怕的 NOLOCK 提示。而且你说这个过程中TableB正在更新。

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

  • 很好的链接,谢谢!当盖尔·肖和保罗·怀特插话时,事情就基本确定了。我确实希望 Microsoft 在这方面有一些文档,或者在我看来更好的是,一篇精心制作、插图完美的 Paul White 文章。:) (2认同)