在SQL Server中使用nolock的实际用途是什么

时间:2012-06-05 11:19:49

标签: sql sql-server sql-server-2008

我在msdn中找到了一些文档,它说“没有发出共享锁,以防止其他事务修改当前事务读取的数据”。

因此,在非专业人士(即我的)中,这会导致读取脏话的问题。哪个太危险了,如果是的话那么为什么要用呢?

是否有人知道将使用它的实际情况。

8 个答案:

答案 0 :(得分:5)

在我们的案例中(上一份工作),我们使用它来获得球场号码。例如,一张表格中包含了在特定日期发送的数百万封电子邮件,如果在5点我们想看到“我们在哪里”,我们可以说:

SELECT COUNT(*) FROM dbo.MessageTable WITH (NOLOCK)
  WHERE CampaignID = x AND CustomerID = y;

很多人会建议将COUNT(*)用于WHERE子句。我认为,如果你愿意接受COUNT(*)中的一些不准确,你也可以这样做:

SELECT SUM(rows) FROM sys.partitions
  WHERE [object_id] = OBJECT_ID('dbo.tablename')
  AND index_id IN (0,1);

由于正在进行的交易,这个数字同样不准确,但实际上并不需要扫描表格,因此效率更高。对于我们的情况,我们甚至可以将其用于子集:使用已过滤的索引(出于其他目的),我们可以类似地查询sys.partitions,但使用过滤索引的index_id

在大多数情况下,使用NOLOCK可能感觉像是一个涡轮按钮,但它可能导致的不准确性很少值得。除非您的系统已经受到严重的tempdb限制,否则您应该考虑READ_COMMITTED_SNAPSHOT代替当前的NOLOCK方案。见Pros and cons of READ_COMMITTED_SNAPSHOT

答案 1 :(得分:1)

我通常使用它来查询我通常用于记录的相对繁忙的表。

SELECT TOP 10 * FROM dbo.MessageLog (NOLOCK) WHERE AppCode = 'DesktopApp' ORDER BY MessageDate DESC

表的记录主要写一次,从不更新。

答案 2 :(得分:1)

如果您愿意接受某些记录可能已过期,则根据具体情况可以提供更快的访问权限。

例如:

SELECT COUNT(*) FROM mytable (nolock) 

将使用更少的资源,并且通常在大型表上比

更快
SELECT COUNT(*) FROM mytable 

答案 3 :(得分:1)

并非所有数据都是相同的。相当多的数据实际上并不重要,因此在某些情况下可以进行脏读。例如,批处理可以批量更新许多不同的表。您可能想要读取用户的读取消息数。你更喜欢这个数字是1还是2,而不是用户必须等待秒,分钟或小时才能获得锁。

换句话说,当实际上不需要确切的数据时,你会增加并发性,并且可以有一些(可能的)无效数据。

答案 4 :(得分:1)

我们有一个表,其中包含一个只插入并更新的队列;什么都没有删除。这些行具有不同的标志,用于指示关联进程发生的情况。生产系统只使用行锁,但一次只有几十个行,因此可以同时进行不同的处理。

我们检查仍在处理的项目数量,以避免系统过载。当用户启动新进程时,它等待生成子进程,直到队列中当前正在处理的项目少于10个。

我们需要防止对可能需要它们更新其所有者状态的进程进行锁定,并且我们需要查看锁定项目的状态。我们使用with (nolock)来防止等待查看队列中发生的事情,并计算尚未标记完成的项目数量 - 逻辑保证只在流程完成时才会发生。

答案 5 :(得分:0)

我们在具有大量读取但很少写入的表上使用它。如果连接只是读取数据,则执行脏读操作通常没有危险。这可以防止阻塞表,从而提高性能。

查看https://stackoverflow.com/a/1453000/1038940以获取有关nolock的更多信息以及何时可能是好/坏

答案 6 :(得分:0)

对我们来说非常简单 - 我们通过nolock提示,财务或定量数据(如价格或余额)与“正常”获取非财务(并且通常很少更改)的数据(如客户地址或商品描述或各种配置选项)锁定。

答案 7 :(得分:0)

你显然是个天才。永远不应该使用它。

NOLOCK经常被用作加速数据库读取的神奇方法,但我尽量避免使用它。

结果集可以包含尚未提交的行,这些行通常会在以后回滚。

错误或结果集可以为空,缺少行或多次显示同一行。

这是因为其他交易在您阅读的同时正在移动数据。

READ COMMITTED增加了一个额外的问题,即单个列中的数据被破坏,其中多个用户同时更改同一个单元格。

还有其他副作用,导致牺牲你希望首先获得的速度增加。

现在你知道了,永远不要用它。