是NOLOCK(Sql Server提示)不好的做法吗?

Pur*_*ome 123 sql t-sql sql-server nolock sql-server-2008

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

那么,有了这个庞大的免责声明,在一些Sql语句中使用NOLOCK提示是不是很糟糕?几年前,一位Sql管理员建议我应该使用NOLOCK,如果我对"脏读"感到满意,这会让我的系统性能提高一些,因为每次读取都没有锁定表/行/不管.

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

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

那么,有些sql db guru sensei的请赐教吗?

Geo*_*gas 105

在使用Stack Overflow之前,我反对NOLOCK委托人,你可以使用可能过期或不一致的数据来执行SELECTwith NOLOCK并获取结果.要考虑的一个因素是可以在同一个表中选择数据的同时插入/更新多少记录.如果这种情况发生很多,那么死锁的可能性很高,除非您使用数据库模式,例如READ COMMITED SNAPSHOT.

我已经改变了我对使用NOLOCK后的看法,见证了它如何提高SELECT性能以及消除大量加载的SQL Server上的死锁.有些时候您可能并不关心您的数据是否完全100%提交,即使它们可能已过期,您也需要快速返回结果.

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

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

如果答案是否定的,则使用NOLOCK提高性能.


我刚刚在NOLOCKStack Overflow的代码库中快速搜索了关键字,发现了138个实例,所以我们在很多地方使用它.

  • 使用"NOLOCK"显然[可以获得重复的行](http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/11/16/1345.aspx).这意味着我必须低估你的答案.抱歉. (9认同)
  • 我不希望减少良好指数覆盖的重要性.有时,使用NOLOCK的查询可以在具有大量插入/更新的表的索引实现的增益之上添加额外的性能.Stack Overflow上的查询速度至关重要,即使数据不准确或丢失也是如此. (8认同)
  • IMO,这有点过分了.可以使用覆盖索引删除死锁,从而减轻Clustered索引的压力. (7认同)
  • @MitchWheat 仅从覆盖索引中读取的“SELECT”可能会导致死锁。SPID 1) 从覆盖索引开始一个“SELECT”。SPID 2) 启动表的“更新”。然后更新继续更新覆盖索引。“UPDATE”到达由“SELECT”锁定的索引范围并被阻止。SPID 1) 仍在寻找覆盖索引,找到由“UPDATE”锁定的范围并被阻止。***僵局***。没有什么可以解决这个死锁(除了捕获 SQL Server 错误 1205,并自动重试,或使用“NOLOCK”) (2认同)
  • 我认为关于这个答案需要注意的重要事项是,它适合于手头的问题.根据您的应用程序,陈旧/未提交/重复/丢失数据的风险可能不值得权衡. (2认同)

OMG*_*ies 67

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

这通常不适合申请.即使您的基于Web的关键任务应用程序的脏读行为正常,NOLOCK扫描也可能导致601错误,由于缺少锁定保护而导致数据移动,这将终止查询.

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

  • 是的,Sam正在说Snapshot隔离,你建议使用Read Committed Snapshot.我很困惑:P(我还没有深入研究这些文章!) (2认同)
  • 它偶尔有用,但通常不适合生产.我经常使用它来提取数据样本以进行测试或生成报告,其中我主要关注粗略的数量级,其中脏读不重要. (2认同)

Mit*_*eat 20

如果您不关心脏读(即主要处于READ状态),那么NOLOCK就可以了.

但是,请注意,大多数锁定问题是由于查询工作负载没有"正确"索引(假设硬件完成任务).

大师的解释是正确的.它通常是解决更严重问题的创可贴解决方案.

编辑:我绝对不建议使用NOLOCK.我想我应该明白这一点.(我只会在极端情况下使用它,我已经分析过它可以).作为一个例子,前一段时间我在一些TSQL上工作,这些TSQL上撒有NOLOCK以试图缓解锁定问题.我删除了所有,实现了正确的索引,所有的死锁都消失了.

  • 嗯..我还是不明白.所以这很好,但它的形式也很差..你说的是什么? (3认同)
  • 好吧,我不认为它的公平rexem只是downvoted,我认为你没有解决当你使用nolock时浮动的任意错误.在你的网站上偶尔获得一个空白错误页面并不好,这是非常糟糕的形式.我不喜欢断言"如果你不关心脏读它的罚款"......它不好,即使你不关心脏读 (2认同)

Gat*_*ats 13

怀疑这是一个"大师"谁有高流量的经验...

当用户查看完全加载的页面时,网站通常是"脏的".考虑一个从数据库加载然后保存编辑的数据的表单?人们继续谈论肮脏的阅读是不可能的,这是愚蠢的.

也就是说,如果你的选择上有许多层,你可能会构建一个危险的冗余.如果您正在处理资金或状态方案,那么您不仅需要事务性数据读/写,还需要适当的并发解决方案(大多数"大师"都不打扰).

另一方面,如果你有一个高级产品搜索网站(即可能不会被缓存并且有点密集的东西)并且你曾经建立过一个拥有多个并发用户的网站(现象有多少) "专家"没有),它背后的每一个过程都是瓶颈.

知道它的含义并在适当的时候使用它.如今,您的数据库几乎总是您的主要瓶颈,并且使用NOLOCK非常聪明可以为您节省数千美元的基础设施.

编辑:它不仅仅是它所帮助的死锁,它也是你要让其他人等到你完成的程度,反之亦然.

在EF4中使用NOLOCK提示?


rea*_*idt 9

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

  • 在查询单个值/行时,使用NOLOCK 总是不好的做法 - 您可能永远不想显示不正确的信息,甚至可能对不正确的数据采取任何操作.
  • 在显示粗略的统计信息时,NOLOCK非常有用.以SO为例:拿锁来读取问题的确切观看次数或标签的确切问题数是毫无意义的.没有人关心你是否错误地陈述了现在用"sql-server"标记的3360个问题,并且由于事务回滚,一秒钟之后会出现3359个问题.