对于NOLOCK或非NOLOCK,这是个问题

时间:2011-01-03 18:48:13

标签: sql-server

这真的是一个讨论,而不是关于nolock的具体问题。

我最近接管了一个应用程序,几乎每个查询(并且有很多查询)都有nolock选项。现在我对SQL服务器(使用Oracle 10年)很新,但我发现这非常令人不安。因此,本周末我与一位经营着相当大的电子商务网站的朋友交谈(名字将被隐瞒以保护有罪的人),他说他必须对他所有的SQL服务器这样做,因为他总是会陷入僵局。

这只是SQL服务器的短暂下降吗?这只是数据库设计中的一个失败(我的不是第三级,但它的关闭)是否有人在那里运行没有nolocks的SQL服务器应用程序?这些是Oracle使用更多宏记录锁更好地处理的问题。

SQL服务器是否无法处理大负载?有没有比阅读未提交的数据更好的解决方法?我很想听听人们的想法。

由于

5 个答案:

答案 0 :(得分:13)

SQL Server在SQL Server 2005中添加了snapshot isolation,这使您仍然可以读取最新的正确值,而无需等待锁定。 StackOverflow也在使用快照隔离。快照隔离级别与Oracle使用的大致相同,这就是为什么死机在Oracle机箱上不常见的原因。如果你启用它,请注意有足够的tempdb空间

来自联机丛书

  

当READ_COMMITTED_SNAPSHOT时   数据库选项设置为ON,读取   提交隔离使用行   版本控制以提供语句级别   读一致性。读操作   只需要SCH-S表级锁   没有页面或行锁。当。。。的时候   READ_COMMITTED_SNAPSHOT数据库   选项设置为OFF,即   默认设置,读取已提交   隔离行为与之前的行为相同   SQL Server的版本。都   实现符合ANSI   读提交的定义   隔离。

答案 1 :(得分:11)

答案 2 :(得分:4)

不,没有必要使用NOLOCK。链接:SO 1

至于加载,我们处理每秒2000行,这与35k TPS

相比变化很小

死锁是由锁争用引起的,通常是由事务中表的写入顺序不一致引起的。 ORM尤其是垃圾。我们很少得到它们。编写良好的DAL也应按MSDN重试。

答案 3 :(得分:2)

在传统的规范化OLTP环境中,NOLOCK是一种代码气味,在设计合理的系统中几乎肯定是不必要的。

在维度模型中,我广泛使用NOLOCK来避免锁定非常大的事实和维度表,这些表格中填充了后来的事实数据(并且维度可能已过期)。在维度模型中,事实要么永远不会改变,要么在某一点之后永远不会改变。类似地,引用的任何维度也将是静态的,因此,例如,NOLOCK将阻止对昨天数据的长分析操作阻止在今天数据的数据加载期间维度到期。

答案 4 :(得分:1)

您应该只在不变的表上使用 nolock 。当然,这与Read Committed Snapshot相同。如果没有快照,您只需节省应用共享锁所需的时间,然后将其删除,这在大多数情况下都不是必需的。

对于更改表...没有锁不只是意味着在事务更新所有行之前获取一行。您可以在数据页面拆分时获取ghost数据,甚至可以拆分索引页面。或者没有数据。仅这一点让我害怕,但我认为可能会有更多的情况,你只是得到错误的数据。

当然,要获得粗略估计或仅仅检查流程的错误可能是合理的。

基本经验法则 - 如果您完全关心数据,并且数据正在发生变化,那么请不要使用NoLOCK。