我想知道如果影响该表的其他查询只有SELECT WITH (NOLOCK)
个查询,那么在表上使用SELECT
有什么好处。
SQL Server如何处理? SELECT
查询会阻止另一个SELECT
查询吗?
我正在使用SQL Server 2012和Linq-to-SQL DataContext
。
(编辑)
关于表现:
SELECT
,第二个SELECT
是否必须等待第一个SELECT
完成?SELECT WITH (NOLOCK)
?答案 0 :(得分:147)
SQL Server中的SELECT
会在表行上放置共享锁 - 而第二个SELECT
也需要共享锁,并且这些锁是一个另一个。
所以没有 - 一个SELECT
无法阻止另一个SELECT
。
WITH (NOLOCK)
查询提示的用途是能够读取正在插入(通过另一个连接)并且尚未提交的数据。
如果没有该查询提示,可能会阻止SELECT
正在通过正在发送独占锁定的INSERT
(或UPDATE
)语句读取表格行(或可能是整个表),直到该操作的事务已提交(或回滚)。
WITH (NOLOCK)
提示的问题是:您可能正在读取根本不会插入的数据行,最后(如果INSERT
事务被回滚) - 所以你的例如报告可能会显示从未真正提交到数据库的数据。
还有另一个可能有用的查询提示 - WITH (READPAST)
。这指示SELECT
命令只是跳过它尝试读取的任何行并且只是被锁定。 SELECT
不会阻塞,也不会读取任何“脏”的未提交数据 - 但它可能会跳过某些行,例如不显示表格中的所有行。
答案 1 :(得分:31)
在表现上,你一直专注于选择
共享不会阻止读取
共享锁块更新。
如果您有数百个共享锁,则需要更新一段时间才能获得独占锁,因为它必须等待共享锁清除。
默认情况下,select(read)采用共享锁 共享(S)锁允许并发事务读取(SELECT)资源 共享锁定对其他选择(1或1000)没有影响。
区别在于nolock与共享锁定效果如何更新或插入操作。
当资源上存在共享(S)锁时,没有其他事务可以修改数据。
共享锁阻止更新!
但是nolock并没有阻止更新。
这会对更新的性能产生巨大影响。它也会影响插入。
脏读(nolock)听起来很脏。你永远不会得到部分数据。如果更新正在将John改为Sally,那么你永远不会得到Jolly。
我使用共享锁来实现并发。一旦读取数据,数据就会过时。阅读约翰,读到下一毫秒的莎莉是陈旧的数据。阅读Sally,在下一毫秒内回滚John是陈旧的数据。那是在毫秒级别。我有一个数据加载器,如果用户正在使用共享锁,需要20个小时才能运行,运行4个小时就是用户无法锁定。在这种情况下,共享锁会导致数据过时16小时。
不要使用错误的nolocks。但他们确实有一席之地。如果要在字节设置为1时剪切检查,然后在剪切检查时将其设置为2,而不是nolock的时间。
答案 2 :(得分:8)
在我的工作中,我们有一个非常庞大的系统,可以在许多PC上同时运行,非常大的表包含数十万行,有时还有数百万行。
当你在一个非常大的表上进行SELECT时,假设你想知道用户在过去10年中所做的每笔交易,并且表的主键没有以有效的方式构建,查询可能需要几分钟才能运行。
然后,我们的应用程序可能会同时在许多用户的PC上运行,访问同一个数据库。因此,如果有人试图插入其他SELECT正在读取的表(在SQL尝试读取的页面中),则可能发生LOCK并且两个事务相互阻塞。
我们必须在SELECT语句中添加一个“NO LOCK”,因为它是一个巨大的SELECT表,很多用户同时使用了很多用户,而且我们一直都有LOCKS。
我不知道我的例子是否足够清楚?这是一个现实生活中的例子。
答案 3 :(得分:7)
我必须添加一条重要评论。每个人都提到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可能会丢失扫描位置,或者您最终可能会获得相同的行两次。
答案 4 :(得分:2)
SELECT WITH (NOLOCK)
允许读取未提交的数据,这相当于在数据库上设置了READ UNCOMMITTED
隔离级别。 NOLOCK
关键字允许比在整个数据库上设置隔离级别更精细的控制。
维基百科有一篇有用的文章:Wikipedia: Isolation (database systems)
在其他stackoverflow文章中也详细讨论了它。
答案 5 :(得分:1)
选择没有锁定 - 将选择可能/可能不会插入的记录。你会读到一个脏数据。
例如- 假设事务插入1000行然后失败。
当您选择时 - 您将获得1000行。