了解SELECT查询上的SQL Server LOCKS

我想知道什么是有利的使用SELECT WITH (NOLOCK)在一个表上,如果唯一影响该表的其他查询是SELECT查询。

SQL Server如何处理? SELECT查询会阻止另一个SELECT查询吗?

我正在使用SQL Server 2012和Linq-to-SQL DataContext

(编辑)

关于performance:

  • 如果使用locking的SELECT第二个SELECT是否必须等待第一个SELECT完成?
  • SELECT WITH (NOLOCK)对比?

谢谢。

SQL Server中的SELECT将在表行上放置一个共享锁 ,而第二个SELECT也需要一个共享锁,并且这些锁相互兼容。

所以没有一个SELECT不能阻塞另一个SELECT

WITH (NOLOCK)查询提示的用途是能够读取正在插入(通过另一个连接)过程中尚未提交的数据。

如果没有这个查询提示, SELECT可能被一个持续的INSERT (或UPDATE )语句读取一个表,这个语句在行(或者可能是整个表)上放置一个排它锁,直到该操作的事务被提交(或回滚)为止。

WITH (NOLOCK)提示的问题是:您最终可能正在读取根本不会被插入的数据行(如果INSERT事务被回滚) – 那么您的报告可能会显示永远不会真正的数据一直致力于数据库。

还有另一个查询提示可能有用 – WITH (READPAST) 。 这将指示SELECT命令跳过它尝试读取的所有行,并且仅被locking。 SELECT不会阻塞,它不会读取任何“脏”未提交的数据,但可能会跳过一些行,例如不显示表中的所有行。

在性能上你一直专注于select。
共享不会阻止读取。
共享锁块更新。
如果你有数以百计的共享锁,它将需要一段时间的更新来获得排它锁,因为它必须等待共享锁清除。

默认情况下,select(读取)将采用共享锁。
共享(S)锁允许并发事务读取(SELECT)资源。
共享locking对其他select(1或1000)没有影响。

区别在于nolock与共享locking效果如何更新或插入操作。

没有其他事务可以修改数据,而资源上存在共享(S)locking。

共享锁会阻止更新!
但nolock不会阻止更新。

这会对更新的性能产生巨大的影响。 它也影响插入。

脏读(nolock)听起来很脏。 你永远不会得到部分数据。 如果一个更新改变约翰到莎莉你永远不会得到快活。

并发使用共享锁很多。 数据一读完就失效了。 读下一个毫秒的约翰改变萨利是陈旧的数据。 读下一个毫秒的Sally回滚约翰是陈旧的数据。 这是毫秒级的。 我有一个数据采集器需要20个小时才能运行,如果用户正在使用共享锁,4小时运行是用户不locking。 在这种情况下共享锁导致数据过时16个小时。

不要使用nolocks错误。 但他们确实有一个地方。 如果你打算在一个字节被设置为1的时候检查一下支票,然后在检查结束时把它设置为2,而不是一个nolock的时间。

我必须添加一个重要的评论。 大家都提到NOLOCK只读脏数据。 这并不准确。 在阅读过程中,您可能会得到相同的行两次或整行被跳过。 原因是当SQL Server重新平衡b-tree时,你可以在同一时间要求一些数据。

检查另一个线程

https://stackoverflow.com/a/5469238/2108874

http://www.sqlmag.com/article/sql-server/quaere-verum-clustered-index-scans-part-iii.aspx

使用NOLOCK提示(或将会话的隔离级别设置为READ UNCOMMITTED),您告诉SQL Server您不期望一致性,因此不能保证。 请记住,“不一致的数据”不仅意味着您可能会看到稍后回滚的未提交更改,或者数据更改处于中间状态。 这也意味着,在扫描所有表/索引数据的简单查询中,SQL Server可能会丢失扫描位置,或者最终可能会获得同一行两次。

在我的工作中,我们有一个非常大的系统,可以同时在许多PC上运行,非常大的表格有成千上万的行,有时甚至有数百万行。

当你在一个非常大的表上做SELECT时,假设你想知道用户在过去10年中所做的每个事务,并且表的主键不是以有效的方式构build的,查询可能需要几分钟的时间跑步。

那么,我们的应用程序可能会同时在许多用户的PC上运行,访问相同的数据库。 所以如果有人试图插入到其他SELECT正在读取的表中(在SQL试图读取的页面中),则可能发生LOCK并且两个事务相互阻塞。

我们不得不在SELECT语句中添加一个“NO LOCK”,因为这是一个巨大的SELECTselect,在很多用户的同时使用很多,而且我们总是使用LOCKS。

我不知道我的例子是否足够清楚? 这是一个真实的例子。

SELECT WITH (NOLOCK)允许读取未提交的数据,这相当于在数据库上设置了READ UNCOMMITTED隔离级别。 NOLOCK关键字允许比在整个数据库上设置隔离级别更细粒度的控制。

维基百科有一篇有用的文章: 维基百科:隔离(数据库系统)

这也是在其他的stackoverflow文章中讨论。

select不locking – 将select可能/不可能插入的logging。 你会读一个脏数据。

例如 – 让一个事务插入1000行然后失败。

当你select – 你会得到1000行。