【问题标题】:SELECT WITH (NOLOCK) sometimes returns no resultsSELECT WITH (NOLOCK) 有时不返回任何结果
【发布时间】:2019-04-22 00:55:23
【问题描述】:

以下查询通常会返回大量结果(大约 750k 个结果)。但是,在生产中,我遇到了返回 0 结果的零星情况。如果我们在它返回 0 后的下一秒重新运行它,它会正常返回结果。

我确信数据仍然存在并且不应该有任何东西会删除它...

我在几个地方看了看,我找不到可能导致上述问题的原因......而且,似乎没有一种简单的方法来复制它......它只是随机的.

由于我的 SQL 知识非常有限,您能否考虑一下可能发生这种情况的某些场景?或者也许建议简单的调试方法?

SELECT MAX(Table1.Cust_ID) AS cust_id, Table1.Email, MAX(Table1.Cust_Name) as cust_name
FROM dbo.Table1 WITH (NOLOCK)
INNER JOIN dbo.Table2 WITH (NOLOCK)
  ON Table1.id = Table2.id
  WHERE Table1.some_id = 100 AND Table1.some_value = 'test_value'
  AND  Table1.some_boolean_1 = 1
  AND  Table1.some_date_1 IS NULL
  AND (Table1.some_boolean_2 IS NULL OR Table1.some_boolean_2 = 1)
  AND (Table1.some_date_2 > '20171119' OR Table1.some_date_3 > '20171119' OR 
       Table2.some_date_3 > '20171119')
GROUP BY Table1.Email

非常感谢!

【问题讨论】:

  • 逐行检查所有那些 WHERE 子句并找到记录脱落的地方?每隔几秒查询一次表并确认记录没有被批量删除?
  • 这很可能是“按设计工作”。 NOLOCK 可以跳过行、重复行和(至少在旧版本中)由于数据移动而出错,尤其是在负载下。如果您需要可靠的结果,请不要使用NOLOCK——坚持使用READ COMMITTED,或者使用快照隔离。 NOLOCK 仅对正确结果并不重要的查询(例如,监视将立即重新运行的查询)远程有用。
  • 是的,nolock 可以跳过行。请参阅dba.stackexchange.com/a/71640/5203 以及那里的链接。
  • NOLOCK 对页面结构执行“原始”读取。它不仅在行级别上不一致,而且根本不一致。它绝对可以跳过您感兴趣的所有行,如果它出现在页面拆分的中间。资料来源:来自一个查询的个人经验,该查询使用GROUP BY 执行了一堆COUNT(*)s,当服务器负载过重时突然开始报告我的表完全为空(显然,它不是)。这个问题只发生过一次,但它已经足够严重,需要切换到快照隔离。
  • 您的查询在语法上不正确 - 可能是由于您的混淆尝试造成的?您不能选择 3 列并仅按其中之一进行分组。

标签: sql sql-server nolock


【解决方案1】:

WITH(NOLOCK) 提示使 SQL Server 以非事务性方式执行查询,这意味着数据完整性被忽略,结果可以是任何类型的中间状态。与将事务隔离级别设置为 READ UNCOMMITTED 的效果相同,但仅适用于此查询。结果还可以包括已插入但尚未提交的行,以及除事务之外运行的任何内容。不知道是什么导致了空结果,但是当修改同时运行时它会返回奇怪的结果。

【讨论】:

  • 我没有否决您的回答,但开头的行 The WITH(NOLOCK) hint makes SQL Server execute the query in a non-transactional way 充其量是误导性的,最坏的情况是不正确的。 WITH(NOLOCK) 忽略底层表上其他打开事务的状态,但这几乎不是“非事务性的”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 2017-12-28
  • 2017-12-09
  • 2020-10-03
相关资源
最近更新 更多