129

我的业务是制作关键任务的网站和应用程序-> 例如。银行软件、太空飞行、重症监护应用程序等。你明白了。

那么,有了这么大的免责声明,在某些 Sql 语句中使用 NOLOCK 提示是否不好?几年前,一位 Sql 管理员建议我应该使用 NOLOCK,如果我对“脏读”感到满意,这会给我的系统带来更多性能,因为每次读取都不会锁定表/行/随便。

我还被告知,如果我遇到死锁,这是一个很好的解决方案。所以,我开始遵循这个想法几年,直到 Sql 大师帮助我编写一些随机代码并注意到我的 sql 代码中的所有 NOLOCKS。我被礼貌地责骂,他试图向我解释(为什么这不是一件好事),我有点迷路了。我觉得他的解释的本质是'这是一个更严重问题的创可贴解决方案.. 特别是如果你遇到僵局。因此,解决问题的根源'。

我最近做了一些谷歌搜索,发现了这篇文章

那么,可以请一些sql db guru sensei 赐教吗?

4

12 回答 12

109

在处理 Stack Overflow 之前,我反对NOLOCK这样的原则,即您可能会使用可能已过时或不一致的数据执行并返回结果SELECTNOLOCK需要考虑的一个因素是可以同时插入/更新多少条记录,另一个进程可能正在从同一个表中选择数据。如果这种情况经常发生,那么死锁的可能性很高,除非您使用数据库模式,例如READ COMMITED SNAPSHOT.

NOLOCK在见证了它如何提高SELECT性能以及消除大规模加载的 SQL Server 上的死锁之后,我改变了我对使用的看法。有时您可能并不关心您的数据并未完全 100% 提交,并且您需要快速返回结果,即使它们可能已过时。

在考虑使用时问自己一个问题NOLOCK

我的查询是否包含具有大量INSERT/UPDATE命令的表,我是否关心从查询返回的数据在给定时刻是否可能缺少这些更改?

如果答案是否定的,那么使用NOLOCK来提高性能。


我刚刚在 Stack Overflow 的代码库中快速搜索了NOLOCK关键字,发现了 138 个实例,因此我们在很多地方都使用了它。

于 2009-09-21T06:25:28.367 回答
70

使用 NOLOCK 提示,该SELECT语句的事务隔离级别为READ UNCOMMITTED. 这意味着查询可能会看到脏数据和不一致的数据。

作为一个规则应用这不是一个好主意。即使这种脏读行为对于您的基于 Web 的关键任务应用程序来说是可以的,NOLOCK 扫描可能会导致 601 错误,这将由于缺乏锁定保护而导致数据移动而终止查询。

我建议阅读快照隔离何时有帮助和何时有伤害- MSDN 建议在大多数情况下使用 READ COMMITTED SNAPSHOT 而不是 SNAPSHOT。

于 2009-09-21T05:25:04.200 回答
20

如果您不关心脏读(即在主要是 READ 的情况下),那就没问题了NOLOCK

但是,请注意,大多数锁定问题是由于没有针对您的查询工作负载的“正确”索引(假设硬件可以胜任该任务)。

上师的解释是正确的。对于更严重的问题,它通常是一种创可贴的解决方案。

编辑:我绝对不建议使用 NOLOCK。我想我应该清楚地说明这一点。(我只会在我分析过它没问题的极端情况下使用它)。举个例子,不久前我在一些 TSQL 上工作,这些 TSQL 已经撒了 NOLOCK 以尝试缓解锁定问题。我将它们全部删除,实现了正确的索引,所有的死锁都消失了。

于 2009-09-21T05:24:42.280 回答
13

怀疑是一位有过高流量经验的“大师”……

当人们查看完全加载的页面时,网站通常是“脏的”。考虑一个从数据库加载然后保存编辑的数据的表单?人们继续认为脏读是这样的不,这是愚蠢的。

也就是说,如果您在选择上构建了多个层,那么您可能会构建危险的冗余。如果您正在处理金钱或状态场景,那么您不仅需要读取/写入事务数据,还需要适当的并发解决方案(大多数“大师”不会打扰)。

另一方面,如果您对网站进行了高级产品搜索(即可能不会被缓存并且有点密集的东西)并且您曾经构建过一个具有多个并发用户的站点(惊人的有多少“专家”没有),将其背后的所有其他流程都扼杀起来是可笑的。

了解它的含义并在适当的时候使用它。这些天,您的数据库几乎总是您的主要瓶颈,并且聪明地使用 NOLOCK 可以为您节省数千美元的基础设施。

编辑:它不仅有助于解决僵局,还在于你要让其他人等到你完成多少,反之亦然。

在 EF4 中使用 NOLOCK 提示?

于 2011-02-23T14:54:44.317 回答
10

没有一个答案是错误的,但可能有点令人困惑。

  • 在查询单个值/行时,使用 NOLOCK总是不好的做法——您可能永远不想显示不正确的信息,甚至可能对不正确的数据采取任何行动。
  • 在显示粗略的统计信息时,NOLOCK 非常有用。以 SO 为例:使用锁来读取问题的确切视图数量,或者标签的确切问题数量是无稽之谈。没有人关心你现在是否错误地用“sql-server”标记了 3360 个问题,并且由于事务回滚,一秒钟后出现了 3359 个问题。
于 2010-08-18T12:28:06.967 回答
2

I agree with some comments about NOLOCK hint and especially with those saying "use it when it's appropriate". If the application written poorly and is using concurrency inappropriate way – that may cause the lock escalation. Highly transactional table also are getting locked all the time due to their nature. Having good index coverage won't help with retrieving the data, but setting ISOLATION LEVEL to READ UNCOMMITTED does. Also I believe that using NOLOCK hint is safe in many cases when the nature of changes is predictable. For example – in manufacturing when jobs with travellers are going through different processes with lots of inserts of measurements, you can safely execute query against the finished job with NOLOCK hint and this way avoid collision with other sessions that put PROMOTED or EXCLUSIVE locks on the table/page. The data you access in this case is static, but it may reside in a very transactional table with hundreds of millions of records and thousands updates/inserts per minute. Cheers

于 2013-02-04T21:56:25.617 回答
2

我相信使用 nolock 几乎是不正确的。

如果您正在读取单行,那么正确的索引意味着您不需要 NOLOCK,因为单个行操作可以快速完成。

如果您正在读取许多行而不是临时显示,并且关心是否能够重复结果,或者通过产生的数字进行辩护,那么 NOLOCK 是不合适的。

NOLOCK 是“我不在乎这个答案是否包含重复的行、已删除的行或由于回滚而从未插入的行”的代理标签

在 NOLOCK 下可能出现的错误:

  • 完全不返回匹配的行。
  • 多次返回单行(包括同一主键的多个实例)
  • 返回不匹配的行。

在 noLock 选择运行时任何可能导致页面拆分的操作都可能导致这些事情发生。几乎任何操作(甚至是删除)都可能导致页面拆分。

因此:如果您“知道”在运行时不会更改行,请不要使用 nolock,因为索引将允许有效检索。

如果您怀疑在查询运行时行可能会更改,并且您关心准确性,请不要使用 nolock。

如果您因为死锁而考虑使用 NOLOCK,请检查查询计划结构是否有意外的表扫描,跟踪死锁并查看它们发生的原因。围绕写入的 NOLOCK 可能意味着先前死锁的查询都可能会写入错误的答案。

于 2014-10-02T22:23:38.503 回答
2

当应用程序支持想要使用 SSMS 回答来自生产服务器的临时查询时(不是通过报告提供的),我要求他们使用 nolock。这样,“主要”业务就不会受到影响。

于 2012-12-21T14:41:10.733 回答
2

如果可能的话,更好的解决方案是:

  • 将您的数据(使用日志复制)复制到报告数据库。
  • 使用 SAN 快照并挂载一致版本的数据库
  • 使用具有更好的基本事务隔离级别的数据库

创建 SNAPSHOT 事务隔离级别是因为 MS 正在失去对 Oracle 的销售。Oracle 使用撤消/重做日志来避免这个问题。Postgres 使用 MVCC。未来 MS 的 Heckaton 将使用 MVCC,但距离生产就绪还需要数年时间。

于 2014-02-07T22:36:14.643 回答
2

作为一名专业的开发人员,我会说这取决于。但我绝对遵循 GATS 和 OMG Ponies 的建议。知道你在做什么,知道什么时候有用,什么时候有害,

阅读提示和其他糟糕的想法

什么可能使您更深入地了解 sql server。我通常遵循 SQL Hints 是 EVIL 的规则,但不幸的是,当我厌倦了强制 SQL 服务器执行某些操作时,我时不时地使用它们……但这些都是极少数情况。

卢克

于 2011-02-23T16:46:21.880 回答
1

NOLOCK 经常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。

结果集可以包含尚未提交的行,这些行通常稍后会回滚。

错误或结果集可以为空、缺少行或多次显示同一行。

这是因为在您读取数据的同时其他事务正在移动数据。

READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。

于 2016-02-05T15:48:45.697 回答
-2

在现实生活中,您遇到已经编写好的系统并向表添加索引,然后显着减慢 14gig 数据表的数据加载速度,有时您被迫在报告和月末处理中使用 WITH NOLOCK,以便聚合函数(总和, count 等)不做行、页、表锁定并降低整体性能。很容易说在新系统中永远不要使用 WITH NOLOCK 并使用索引 - 但是添加索引会严重降低数据加载的等级,当我被告知时,好吧,更改代码库以删除索引,然后批量加载然后重新创建索引 - 这一切都很好,如果您正在开发一个新系统。但不是当你有一个系统已经到位时。

于 2016-08-10T09:41:10.367 回答