我在 msdn 中浏览了一些文档,它说“没有发出共享锁来防止其他事务修改当前事务读取的数据”。
所以在外行术语(即我的)这会导致脏读的问题。哪个太危险了,如果是,那为什么要使用它?
有谁知道使用它的实际场景。
我在 msdn 中浏览了一些文档,它说“没有发出共享锁来防止其他事务修改当前事务读取的数据”。
所以在外行术语(即我的)这会导致脏读的问题。哪个太危险了,如果是,那为什么要使用它?
有谁知道使用它的实际场景。
在我们的案例(以前的工作)中,我们使用它来获取球场数字。因此,例如一个包含在给定日期发送的数百万封电子邮件的表格,如果我们想在 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 的优缺点
我们有一个表,其中包含一个仅插入和更新的队列;什么都不会被删除。这些行具有不同的标志,指示相关进程正在发生什么。生产系统只使用行锁,但在不同的行上一次持有几十个,这样不同的进程就可以同时发生。
我们检查有多少项目仍在处理中,以避免系统过载。当用户启动一个新进程时,它会等待生成子进程,直到队列中当前正在处理的项目少于 10 个。
我们需要防止对可能需要它们更新自己状态的进程进行锁定,并且我们需要查看锁定项的状态。我们with (nolock)
用来防止等待查看队列中发生的事情,并计算有多少项目尚未标记为完成 - 逻辑保证仅在流程完成时发生。
并非所有数据都是平等的。相当多的数据实际上并不重要,因此在某些情况下进行脏读是可以的。例如,批处理可以批量更新许多不同的表。您可能想要读取用户的已读消息数。您更喜欢数字超出 1 或 2,而不是用户必须等待几秒钟、几分钟或几小时才能使锁可用。
换句话说,当实际上不需要确切的数据时,您正在增加并发性,并且可以有一些(可能)无效数据。
我通常使用它来查询我通常用于记录的相对繁忙的表。
SELECT TOP 10 * FROM dbo.MessageLog (NOLOCK) WHERE AppCode = 'DesktopApp' ORDER BY MessageDate DESC
表的记录主要写入一次,从不更新。
如果您愿意接受某些记录可能已过期,则根据具体情况,它可以提供更快的访问。
例如:
SELECT COUNT(*) FROM mytable (nolock)
将使用更少的资源,并且通常比在大表上更快
SELECT COUNT(*) FROM mytable
我们在有大量读取但很少写入的表上使用它。如果连接只是读取数据,那么进行脏读通常没有危险。这可以防止阻塞表,从而提高性能。
查看https://stackoverflow.com/a/1453000/1038940了解有关 nolock 的更多信息以及何时可以是好/坏
对我们来说很容易 - 我们获取非财务(通常很少更改)数据(如客户地址或商品描述或各种配置选项),带有 nolock 提示,财务或定量数据(如价格或余额)带有“正常”锁定。
你显然是个天才。它不应该被使用。
NOLOCK 经常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。
结果集可以包含尚未提交的行,这些行通常稍后会回滚。
错误或结果集可以为空、缺少行或多次显示同一行。
这是因为在您读取数据的同时其他事务正在移动数据。
READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。
还有其他副作用,这会导致牺牲您最初希望获得的速度提升。
现在你知道了,永远不要使用它。