了解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行。