NOLOCK(SQL Server提示)不好的做法?

我在做网站和应用程序不是任务关键 – 例如。 银行软件,太空飞行,重症监护应用程序等等。你明白了。

那么,在这个庞大的免责声明中,在某些Sql语句中使用NOLOCK提示是不是很糟糕? 几年前,一位Sqlpipe理员build议,如果我对“脏读”感到满意,那么我应该使用NOLOCK,这将使我的系统性能提高一倍,因为每次读取都不会locking表/行/不pipe。

我也被告知,如果我遇到死锁,这是一个很好的解决scheme。 所以,我开始思考了几年,直到一个Sql guru帮我一些随机代码,并注意到我的sql代码中的所有NOLOCKS。 我被礼貌地骂了,他试图向我解释(为什么这不是一件好事),我有点失落。 我觉得他的解释的本质是“这是一个更严重的问题的创可贴解决scheme,特别是如果你遇到了僵局。 因此,解决问题的根源“。

我最近做了一些Googlesearch,碰到这个post 。

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

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

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

我build议阅读当快照隔离有帮助和什么时候它伤害 – MSDNbuild议在大多数情况下使用READ COMMITTED SNAPSHOT而不是SNAPSHOT。

在使用Stack Overflow之前,我曾经反对NOLOCK ,你可能会用NOLOCK执行一个SELECT ,然后返回可能过时或不一致的数据。 需要考虑的一个因素是可以同时插入/更新多less个logging,同时另一个进程可以从同一个表中select数据。 如果发生这种情况,那么除非使用数据库模式(如READ COMMITED SNAPSHOT否则很有可能出现死锁。

我已经改变了对使用NOLOCK看法,目睹了它如何提高SELECT性能以及消除大规模加载的SQL Server上的死锁。 有时候,您可能并不关心您的数据不完全是100%提交的,即使这些数据可能已经过期,也需要尽快恢复。

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

我的查询是否包含一个具有大量INSERT / UPDATE命令的表,如果从查询返回的数据可能在给定时刻缺less这些更改,我该怎么处理?

如果答案为否,则使用NOLOCK提高性能。


我只是在Stack Overflow的代码库中快速search了NOLOCK关键字,发现了138个实例,所以我们在很多地方使用它。

如果你不关心肮脏的阅读(即主要是阅读情况),那么NOLOCK是好的。

但是 ,请注意,大多数locking问题是由于对查询工作负载没有“正确的”索引(假设硬件完成任务)。

上师的解释是正确的。 它通常是一个更严重的问题的创可贴解决scheme。

编辑 :我绝对不是build议使用NOLOCK。 我想我应该明确地表明这一点。 (我只会使用它,在极端的情况下,我曾经分析过它是可以的)。 作为一个例子,后来我工作了一些已经被NOLOCK撒上的TSQL来尝试和缓解locking问题。 我全部删除了它们,执行了正确的索引,所有的僵局都消失了。

怀疑这是一个谁在高stream量有任何经验的“大师”

当人们查看完全加载的页面时,网站通常是“脏的”。 考虑从数据库加载的表单,然后保存编辑的数据? 人们继续讨论肮脏的阅读方式是不可能的。

也就是说,如果你的select有多个层次,那么你可能会构build一个危险的冗余。 如果您正在处理金钱或状态情况,那么您不仅需要事务性数据读取/写入,而且还需要一个适当的并发解决scheme(大多数“权威”并不打扰)。

另一方面,如果你有一个先进的产品search网站(即有可能不会被caching,并有一点密集),你曾经build立了一个网站与less数并发用户(phenominal多less“专家”还没有),把它背后的其他过程弄得一团糟。

知道它是什么意思,并在适当的时候使用它。 现在你的数据库将永远是你的主要瓶颈,而且使用NOLOCK可以为你节省成千上万的基础设施。

编辑:这不仅仅是它帮助的死锁,它也是多less你要让其他人等待,直到你完成,反之亦然。

在EF4中使用NOLOCK提示?

没有一个答案是错的,但也许有点混乱。

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

作为一个专业的开发人员,我会说这取决于。 但我绝对遵循GATS和OMG小马的build议。 知道你在做什么,知道什么时候有帮助,什么时候疼

阅读提示和其他不好的想法

什么可能会让你更深入地理解sql服务器。 我通常遵循SQL提示是EVIL的规则,但不幸的是,当我厌倦了强迫SQL服务器做事情时,我不时地使用它们…但是这些是罕见的情况。

卢克

当应用程序支持要使用SSMS(不适合通过报告)从生产服务器回答广告查询时,我要求他们使用nolock。 这样,“主要”业务就不受影响。

我同意一些关于NOLOCK暗示的评论,尤其是那些说“在适当的时候使用它”的评论。 如果应用程序写得不好并且使用并发性不当的方式 – 那可能会导致锁升级。 由于其性质,高度交易的桌子也一直处于locking状态。 具有良好的索引覆盖率将无助于检索数据,但将“隔离级别”设置为“未读未读”。 另外我相信,在许多情况下,使用NOLOCK提示是安全的,因为变化的性质是可以预测的。 例如 – 在制造时,当旅行者的工作经历了大量插入测量的不同过程时,您可以使用NOLOCK提示安全地执行对完成作业的查询,并且这样可以避免与其他将PROMOTED或EXCLUSIVE锁放在桌面上的会话相冲突/页。 在这种情况下访问的数据是静态的,但它可能驻留在一个非常事务性的表中,每分钟有数以亿计的logging和数千次更新/插入。 干杯

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

如果您正在阅读单行,则正确的索引意味着您将不需要NOLOCK,因为快速完成单个行操作。

如果您正在读取多行而不是临时显示,并且关心是否能够重复结果,或者由生成的数字来防守,那么NOLOCK是不合适的。

NOLOCK是“我不在乎这个答案是否包含重复的行,删除的行或者是因为回滚而从未被插入的行”

在NOLOCK下可能出现的错误:

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

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

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

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

如果由于死锁而考虑NOLOCK,请检查查询计划结构以查找意外的表扫描,追踪死锁并查看出现的原因。 写周围的NOLOCK可能意味着先前死锁的查询可能会写错误的答案。

如果可能,更好的解决scheme是:

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

SNAPSHOT事务隔离级别是由于MS销售给Oracle而导致的。 Oracle使用撤销/重做日志来避免这个问题。 Postgres使用MVCC。 将来,MS的Heckaton将使用MVCC,但是距离生产准备还有几年的时间。

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

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

错误或结果集可能为空,可能缺less行或多次显示相同的行。

这是因为其他交易是在您读取数据的同时移动数据。

READ COMMITTED会在单个列中多个用户同时更改同一个单元格的情况下增加了一个额外的问题。

在现实生活中,如果遇到已经编写好的系统并向表中添加索引,然后大大减慢了14gig数据表的数据加载速度,则有时候会被迫在报告和月底使用WITH NOLOCK,以便汇总函数,计数等)不要做行,页面,表锁,并降低整体性能。 在一个新的系统中很容易说,不要使用WITH NOLOCK并使用索引 – 但是添加索引会严重降级数据加载,而当我被告知时,更改代码库以删除索引,然后批量加载然后重新创build索引如果你正在开发一个新的系统,那么这一切都很好。 但是,当你有一个系统已经到位。