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