4

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

所以在外行术语(即我的)这会导致脏读的问题。哪个太危险了,如果是,那为什么要使用它?

有谁知道使用它的实际场景。

4

8 回答 8

5

在我们的案例(以前的工作)中,我们使用它来获取球场数字。因此,例如一个包含在给定日期发送的数百万封电子邮件的表格,如果我们想在 5:00 看到“我们在哪里”,我们可以说:

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场景。查看READ_COMMITTED_SNAPSHOT 的优缺点

于 2012-06-05T12:17:31.917 回答
1

我们有一个表,其中包含一个仅插入和更新的队列;什么都不会被删除。这些行具有不同的标志,指示相关进程正在发生什么。生产系统只使用行锁,但在不同的行上一次持有几十个,这样不同的进程就可以同时发生。

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

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

于 2012-06-05T12:58:55.940 回答
1

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

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

于 2012-06-05T11:27:11.493 回答
1

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

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

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

于 2012-06-05T11:24:36.173 回答
1

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

例如:

SELECT COUNT(*) FROM mytable (nolock) 

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

SELECT COUNT(*) FROM mytable 
于 2012-06-05T11:24:38.163 回答
0

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

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

于 2012-06-05T11:26:07.590 回答
0

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

于 2012-06-05T11:37:48.930 回答
0

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

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

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

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

这是因为在您读取数据的同时其他事务正在移动数据。

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

还有其他副作用,这会导致牺牲您最初希望获得的速度提升。

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

于 2016-02-05T16:09:22.520 回答