我在msdn中找到了一些文档,它说“没有发出共享锁,以防止其他事务修改当前事务读取的数据”。
因此,在非专业人士(即我的)中,这会导致读取脏话的问题。哪个太危险了,如果是的话那么为什么要用呢?
是否有人知道将使用它的实际情况。
答案 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增加了一个额外的问题,即单个列中的数据被破坏,其中多个用户同时更改同一个单元格。
还有其他副作用,导致牺牲你希望首先获得的速度增加。
现在你知道了,永远不要用它。