NOLOCK会导致DISTINCT失败吗?

时间:2017-10-19 17:15:01

标签: sql-server

免责声明:这不是关于NOLOCK问题的一般性问题(因此不是Is the NOLOCK (Sql Server hint) bad practice?的副本);这是一个特定的问题,关于NOLOCK和DISTINCT如何交互以试图更好地理解SQL Server的内部工作。

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

INSERT INTO TableA (ID)
SELECT DISTINCT ID
FROM TableB WITH (NOLOCK)

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

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

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

任何人都可以证实吗?如果是这样,这是设计,还是SQL Server中的错误?

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

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

1 个答案:

答案 0 :(得分:3)

肯定会发生这种情况。该引擎足够聪明,知道由于ID是您的主要密钥,因此不会浪费资源来查找重复项。但是,您已经介绍了可怕的NOLOCK提示。你说在这个过程中TableB正在更新。

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