免责声明:这不是关于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违规。以下是其他相关事实:
我的工作理论是:1)TableB上的更新与NOLOCK的使用相结合导致重复数据,2)优化器依赖于TableA在我们正在进行DISTINCTing的同一列上有PK的事实,以及所以不主动对返回的行执行DISTINCT操作,它只是假设行已经是不同的。
任何人都可以证实吗?如果是这样,这是设计,还是SQL Server中的错误?
我原本以为即使是脏读也有重复行的可能性,DISTINCT将是清理重复项的保证,但我看到的证据似乎表明不是这样。
在SQL Server 2008R2上看到此错误。
答案 0 :(得分:3)
肯定会发生这种情况。该引擎足够聪明,知道由于ID是您的主要密钥,因此不会浪费资源来查找重复项。但是,您已经介绍了可怕的NOLOCK提示。你说在这个过程中TableB正在更新。
你几乎肯定在这里遇到的是页面拆分带来的NOLOCK的副作用。这些页面拆分可能导致引擎返回重复的行,正如我之前所说,引擎假定您没有重复项,因为您正在选择主键,并且不能重复。这不是sql server中的错误,这是停止使用提示的另一个原因。