要NOLOCK还是不要去NOLOCK?

时间:2014-06-27 08:30:42

标签: sql-server tsql

我曾在一个非常庞大的组织工作,他们必须在大多数查询中使用NOLOCK - 因为数据通常在白天通过ETL流程更新,并在40%的工作日内锁定应用程序当然不是一个选择。

出于习惯,在我的下一个地方,我继续在任何地方自动使用NOLOCK。但是,自从阅读警告和风险以来,我已经逐渐撤消了这一点,没有指定任何表提示,让SQL Server做了它。

然而,我仍然不习惯我做正确的事情。在我们使用NOLOCK的地方,我从未见过数据加倍或数据损坏。我在那里待了很多年。自从删除NOLOCK以来,我遇到了明显阻碍行阻塞的问题,这些障碍减缓/暂停了查询,从而产生了我的数据库缓慢或松散的错觉。实际上,只是有人在某处运行冗长的保存(他们这样做的能力是应用程序的要求)。

我很想听听任何在实践中遇到NOLOCK数据损坏或数据重复的人,而不是那些在互联网上阅读过他们的人。如果有人能提供复制步骤来看到这种情况,我将特别感激。我试图衡量它的风险程度,并且风险是否超过能够运行与更新平行的报告的明显好处?

2 个答案:

答案 0 :(得分:5)

我已经看到NOLOCK的损坏,重复和糟糕的结果。不是一次,也不是很少。 依赖于NOLOCK的每个部署,我有机会查看正确性问题。确实很多(大多数?)没有意识到并且没有意识到,但问题始终存在。

你必须意识到NOLOCK问题没有表现为硬破坏(DBCC CHECKDB会报告的那种),但是'软'腐败。并且这些问题仅在某些类型的工作负载上很明显,主要是在分析类型(聚合)上。它们会在报告中显示为不正确的值,分类帐中的余额不匹配,错误的部门人数和类似情况。只有在合格的人员仔细检查时,这些问题才会显现为问题。它们可能会在页面的简单刷新上神秘地消失。所以你很可能遇到所有这些问题,而不是意识到它们。您的用户可能会接受这种情况,有时候余额是错误的,只需再次询问报告,就可以了。并且从不向你报告这个问题。

还有一些工作负载对NOLOCK问题不是很敏感。如果你显示'帖子'和评论'你不会看到很多NOLOCK问题。可能是“未答复的数字”'是2,但谁会注意到?

  

自从删除NOLOCK后,我遇到了明显阻碍行阻塞减缓/暂停查询的障碍

我建议评估SNPASHOT隔离模型(包括READ_COMMITTED_SNAPSHOT)。你可以免费享用午餐。

答案 1 :(得分:2)

我看到你已经阅读了很多关于它的内容,但是请允许我指出一个关于使用NOLOCK的危险的非常好的解释(那就是READ UNCOMMITTED隔离级别):SQL Server NOLOCK Hint & other poor ideas.

除此之外,我会做一些引用和评论。 NOLOCK最糟糕的部分就是:

  

它创造了“非常难以重现”的错误。

问题在于,当您读取未提交的数据时,大部分时间都是提交的,所以一切都很顺利。但如果交易没有进行,它将随机失败。而这通常不会发生。对?不,首先,单个错误是一件非常糟糕的事情(您的客户不喜欢它)。第二,事情会变得更糟,LO:

  

问题在于,事务不仅仅是更新行。它们通常需要更新索引,或者数据页面上的空间不足。这可能需要分配新页面和该页面上要移动的现有行,称为PageSplit。您的选择可能会完全错过许多行和/或计算其他行两次。 链接文章中的更多信息

因此,这意味着即使您已读取的未提交事务已提交,您仍然可以读取错误数据。而且,这将在随机时间发生。那很难看,非常难看!

腐败怎么办?

正如Remus Rusanu所说,这不是“硬”而是“软”腐败。它会影响特定的聚合,因为您正在阅读更新时不应该阅读的内容。这可能会导致错误的帐户余额。

您是否听说过大型LOB应用程序有重建帐户余额的程序?为什么?他们应该在交易内正确更新! (如果在关键时刻重建余额,这是可以接受的,例如在计算税收时)。

如果不破坏数据,我可以做些什么(因此相对安全)?

让我们说当您不使用它来更新数据库上的其他现有数据时,读取非公开数据是“非常安全的”。即如果您仅将NOLOCK用于报告目的(没有回写),那么您就处于“非常安全”的一面。唯一的“小麻烦”是报告可以显示错误的数据,但至少DB中的数据会保持一致。

考虑到这种安全取决于你正在阅读的内容。如果它是信息性的,不会被用来做出决定,这是非常安全的(例如,在最好的客户或最畅销的产品的报告上有一些错误并不是很糟糕)。但是如果你得到这些信息来做出决定,情况可能会更糟(你可以在错误的基础上作出决定!)

特殊体验

我致力于开发一个'拥挤'的应用程序,有大约1,500名用户使用NOLOCK读取数据,修改它在DB(HHRR / TEA公司)上的更新。 (显然)没有问题。诀窍在于每个员工都读取“原子数据”(员工的数据)来修改它,两个人几乎不可能同时读取和修改相同的数据。除此之外,“原子数据”不影响任何聚合数据。所以一切都很好。但是报告区域不时出现问题,用NOLOCK读取“汇总数据”。因此,关键报告必须安排在没有人在DB中工作的时刻。对非关键性报告的小偏差被忽视和承认。

现在你知道了。你没有任何借口。您决定NOLOCK是否与NOLOCK