我想知道SELECT WITH (NOLOCK)
如果影响该表的其他唯一查询是SELECT
查询,在表上使用的好处是什么?
SQL Server如何处理?一个SELECT
查询会阻止另一个SELECT
查询吗?
我正在使用SQL Server 2012和Linq-to-SQL DataContext
。
(编辑)
关于性能:
- 如果使用锁定功能,第二个
SELECT
必须等待第一个SELECT
完成SELECT
吗? - 与一个
SELECT WITH (NOLOCK)
?
Answers:
SELECT
SQL Server中的A将在表行上放置一个共享锁-第二个SELECT
也将需要共享锁,并且它们彼此兼容。
所以没有人SELECT
可以阻挡别人SELECT
。
什么WITH (NOLOCK)
查询提示用于是能够读取数据的插入(由其它连接)的过程,是和尚未提交。
如果没有该查询提示,则SELECT
可能会通过正在执行INSERT
(或UPDATE
)的语句在行(或可能是整个表)上设置排他锁的语句来阻止a读取表,直到该操作的事务已提交(或回滚)为止。
WITH (NOLOCK)
提示的问题是:您可能正在读取最终根本不会插入的数据行(如果INSERT
事务回滚了),因此您的例如报告可能显示从未真正提交到数据库的数据。
还有另一个查询提示可能有用- WITH (READPAST)
。这指示SELECT
命令仅跳过它尝试读取且被独占锁定的任何行。该SELECT
不会阻止,它将无法读取任何“脏”未提交的数据-但它可能会跳过某些行,如不显示在表中所有的行。
在性能方面,您会一直专注于选择。
共享不会阻止读取。
共享锁块更新。
如果您有数百个共享锁,则它需要花费一段时间才能获得排他锁,因为它必须等待共享锁清除。
默认情况下,选择(读取)具有共享锁。
共享(S)锁允许并发事务读取(SELECT)资源。
共享锁不会影响其他选择(1或1000)。
区别在于nolock和共享锁效果如何更新或插入操作。
资源上存在共享(S)锁时,没有其他事务可以修改数据。
共享锁会阻止更新!
但是nolock不会阻止更新。
这可能对更新的性能产生巨大影响。它还会影响刀片。
脏读(nolock)听起来很脏。您永远不会获得部分数据。如果更新将John更改为Sally,那么您永远都不会得到Jolly。
我经常使用共享锁来实现并发。数据一被读取就过时。在下一个毫秒内将John更改为Sally的读数是陈旧的数据。对Sally的读取会在下一个毫秒内回滚到John,这是陈旧的数据。那是毫秒级的。我有一个数据加载器,如果用户使用共享锁,则需要20个小时才能运行;如果用户没有锁,则需要4个小时才能运行。在这种情况下,共享锁导致数据过时16小时。
不要误用nolock。但是他们确实有地方。如果要在字节设置为1时削减支票,然后在削减支票时将其设置为2-则不是空锁的时间。
我必须添加一个重要的评论。每个人都提到NOLOCK
只读取脏数据。这不准确。也有可能两次读取相同的行,或者在读取过程中跳过了整行。原因是当SQL Server重新平衡b树时,您可能同时要求一些数据。
检查其他线程
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年中进行的每笔交易,并且该表的主键不是以有效的方式构建的,因此查询可能需要几分钟的时间跑步。
然后,我们的应用程序可能会同时在许多用户的PC上运行,并访问相同的数据库。因此,如果有人试图将另一个SELECT正在读取的表插入到表中(在SQL试图读取的页面中),则可能发生LOCK,并且两个事务相互阻塞。
我们必须在SELECT语句中添加“ NO LOCK”,因为这是对表的巨大SELECT,同时很多用户都在使用该表,并且一直都有LOCKS。
我不知道我的例子是否足够清楚?这是一个真实的例子。
在SELECT WITH (NOLOCK)
未提交的数据,这相当于具有允许读取READ UNCOMMITTED
您的数据库隔离级别设置。NOLOCK
与在整个数据库上设置隔离级别相比,该关键字允许更精细的控制。
Wikipedia有一篇有用的文章:Wikipedia:隔离(数据库系统)
其他stackoverflow文章中也对此进行了详细讨论。
READUNCOMMITTED
(的别名NOLOCK
)提示。这样做使得实际的操作(实际上并不是“没有锁”)变得不太清楚。
SELECT
使用会对数百个查询产生影响WITH (NOLOCK)
吗?