标签: nolock

NOLOCK 总是不好?

我是一名报表开发人员,希望尽可能提高我的查询效率。我曾经与一位 DBA 一起工作,他告诉我 - 我相信是因为我总是在生产服务器上处理报告 -NOLOCK在每个查询中使用。

现在,我与一个NOLOCK在任何情况下都被禁止的 DBA 一起工作- 即使我的报告(由于几个表上缺乏索引)正在停止复制和系统更新。在我看来,在这种情况下,aNOLOCK将是一件好事。

由于我的大部分 SQL 培训都是来自不同意见的 DBA,因此我想向各种各样的 DBA 提出这个问题。

sql-server locking nolock

34
推荐指数
4
解决办法
4430
查看次数

(NOLOCK) VS NOLOCK

当我看到一个看起来像这样的查询时,我正在调查一些阻塞:

SELECT SomeField FROM SomeTable NOLOCK
Run Code Online (Sandbox Code Playgroud)

我看到了NOLOCK并且很好奇它是如何阻塞其他查询的,在这种情况下是DELETE语句。我快速查看了使用的锁sp_lock,这是我所看到的:

DB      S   GRANT

TAB     IS  GRANT

PAG    S    GRANT
Run Code Online (Sandbox Code Playgroud)

现在,我的理解是NOLOCK应该只需要一个 Schema-Stability 锁,为什么它会抓住一个 IS 锁?

我的好奇心被勾起来了。我查看了 BOL,发现有两种使用方法,WITH (NOLOCK)以及已弃用的 . (NOLOCK),所以我决定尝试一下。我运行了以下查询,然后运行sp_lock:

SELECT SomeField FROM SomeTable WITH (NOLOCK)
Run Code Online (Sandbox Code Playgroud)
DB S 赠款

TAB Sch-S 授权
SELECT SomeField FROM SomeTable (NOLOCK)
Run Code Online (Sandbox Code Playgroud)
DB S 赠款

TAB Sch-S 授权

果然,有我的模式稳定性锁。所以我的问题是:这里发生了什么?如果使用 NOLOCK 的公认语法是WITH (NOLOCK)or (NOLOCK),那么为什么查询在只使用普通NOLOCK(不带括号)运行时不会出错?如果支持,为什么要抢 IS 锁?我在这里缺少什么?我一直在网上搜索答案,但到目前为止还不够。

我已经在 2008R2 和 2012 上对此进行了测试。

sql-server syntax nolock

24
推荐指数
1
解决办法
4014
查看次数

证明在每个查询中不使用 (nolock) 提示

您是否曾经不得不证明不使用查询提示是合理的?

我WITH (NOLOCK)在每个访问非常繁忙的服务器的查询中都看到了。开发人员认为它应该默认开启,因为他们讨厌在他们的代码中看到它数千次。

我试图解释说它允许脏读,最终它们会得到坏数据,但他们认为性能权衡是值得的。(他们的数据库一团糟;难怪他们有性能问题。)

如果你有一个明确的例子来说明如何反对这种滥用NOLOCK提示的情况,那将不胜感激。

sql-server locking nolock

23
推荐指数
3
解决办法
4972
查看次数

由于数据移动,无法使用 NOLOCK 继续扫描

我们运行 SQL Server 2000,每天晚上都会遇到一些这样的错误。

Could not continue scan with NOLOCK due to data movement
Run Code Online (Sandbox Code Playgroud)

引发此错误的查询是一个大型复杂查询,它连接了十多个表。我们的基础数据可以经常更新。

文化“最佳实践”是,在过去,NOLOCK提示的引入提高了性能并改进了并发性。这个查询不需要 100% 准确,即我们会容忍脏读等。然而,我们正在努力理解为什么数据库会抛出这个错误,即使我们有所有这些锁定提示。

任何人都可以对此有所了解 - 温柔一点,我实际上是一名程序员,而不是 DBA :)

PS:我们已经应用了前面提到的修复:http : //support.microsoft.com/kb/815008

sql-server-2000 database-tuning locking nolock

10
推荐指数
1
解决办法
2万
查看次数

如何重现“由于数据移动,无法继续使用 NOLOCK 扫描”

我偶尔会NOLOCK在一些大型作业中遇到“由于数据移动而无法继续扫描”,这些作业WITH (NOLOCK)在选择查询中确实有。

我知道这与在页面拆分导致数据不再位于应有的位置时尝试选择数据有关 - 我认为这就是我的环境中发生的情况。

我将如何重现这个?

我正在尝试做一个短期的解决方法来捕捉错误并在发生这种情况时重试,但如果我无法重现它,我将无法对其进行测试。有没有合理可靠的方法来导致这种情况?

当它发生时,再次执行查询会导致成功 - 所以我真的不担心实际数据或数据库被永久损坏。查询中的一些表(连同它们的索引)经常被删除、重新创建和重新填充,所以我假设它与此相关。

移除NOLOCK是我要处理的长期问题。NOLOCK放在那里的原因首先是查询非常糟糕,以至于它们因日常事务而陷入僵局,因此可以NOLOCK使用创可贴来阻止僵局(有效)。所以我需要一个创可贴,直到我们可以做一个永久性的解决方案。

如果我可以用 Hello World 重现它,我可能会计划在不到一个小时的时间内将创可贴贴到工作中。无法执行搜索和替换删除NOLOCK,因为我会再次开始使应用程序陷入僵局,这对我来说比偶尔失败的工作更糟糕。

使用读提交的快照隔离是一个很好的可能性 - 我将不得不与我们的数据库团队合作以获取更多详细信息。我们的部分问题是我们没有 SQL Server 专家来处理这类事情,而且我对隔离级别的了解还不够充分,无法立即进行更改。

sql-server sql-server-2008-r2 nolock

10
推荐指数
1
解决办法
4003
查看次数

调用表值函数时使用 NOLOCK 提示

假设有以下函数:

CREATE FUNCTION [dbo].[ufnTest]()
RETURNS TABLE
AS RETURN SELECT 1 AS Nr
Run Code Online (Sandbox Code Playgroud)

我的实际函数将从许多不同的表中选择实际数据。我(大部分)理解使用 nolock 提示的风险,并决定在这种情况下我真的想要它们。所以我尝试像这样调用上面的函数:

SELECT * FROM [dbo].[ufnTest]() WITH(NOLOCK)
Run Code Online (Sandbox Code Playgroud)

但是,这失败并显示以下消息:

关键字“with”附近的语法不正确。如果此语句是公共表表达式、xmlnamespaces 子句或更改跟踪上下文子句,则前一条语句必须以分号终止。

修复此错误的提示不相关。也许这个表提示不适用于表值函数?

我会考虑几种选择。一种是在我的选择查询中的所有表上使用提示,但我不想这样做,因为 (a) 每当我更改函数时我都必须记住这一点,并且 (b) 它是重复的。另一种选择是SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED,但缺点是我不太知道如何将它设置回之前的状态(并且从我的 TVF 选择之后的语句应该具有原始隔离级别)。

因此,我更愿意WITH (NOLOCK)从表值函数中进行选择。这可能吗?

sql-server sql-server-2012 functions nolock

8
推荐指数
1
解决办法
1万
查看次数

如何证明 NOLOCK 是死锁问题的根源?

我不是要开始 Windows/mac 类型的讨论。

就我个人而言,我不需要任何令人信服的NOLOCK作为反思性练习的好主意。似乎在开发时一切都应该是有目的的而不是反动的 (/amen)

所以......负责程序员坚持NOLOCK是要走的路。推荐所有临时查询和查询生产时。我还没有在每个表上看到没有 nolock 提示的存储过程。

不要成为那种走进来告诉每个人核心信念都是错误的,而没有任何支持的人。

仅查看各种博客文章下的评论会话,发送链接可能还不够。长期持有的信念等......有些人不相信这是一个问题。请参阅:我读过的每篇 nolock 博客文章下的评论部分。

目前,其他一些 DBA 正在与一些神秘的僵局搏斗。如何确定 NOLOCK 是否是来源?

有人建议从跟踪等中查看 XML,但这不会明确说明死锁是导致问题的原因,是吗?我从来没有看到过直接的错误消息。真的吗?

否则这些僵局怎么可能被钉在这个上面?

DDL 语句就像CREATE是一个线索。在我发出警报之前,是否有任何我可以指出的输出或我可以找到的一些数据可以帮助证实我的理论?

或者我是否运行跟踪标志或扩展事件来识别发生死锁时正在运行的内容,然后从 DDL 语句中推断?

看看数据可能被 nolock 提示弄乱的所有不同方式,果断地确定似乎是一个困难的问题。

sql-server nolock

8
推荐指数
1
解决办法
963
查看次数

在这种情况下使用 WITH (NOLOCK) 安全吗?

设想

我有一个处理并发 SELECT 和 DELETE 的表。我的 SELECT 语句出现了一些死锁。我假设来自其他事务的 DELETE 正在获取排他锁并与 SELECT 的共享锁冲突。

细节

  • SQL Server 14.00.3281.6.v1
  • 在 AWS RDS 上运行

用例

  • 我的应用程序可以通过多种方式触发 SELECT。
  • 如果应用程序触发 DELETE,它将(总是)触发 SELECT 以检索反映 DELETE 效果的结果。

在并发 SELECT 和 DELETE 的情况下,它可能看起来像这样(在 MS Paint 中绘制,因为我试图变得专业......):

时间线图片

编辑:上面的“触发器”不是指实际的数据库触发器,而是指应用程序行为。

研究

我在 DBA Stack Exchange 上四处闲逛,发现我可以SELECT myTable WITH (NOLOCK)阻止共享锁。我正在考虑使用它,但我知道有很多警告和问题,所以我想验证我的决定或在必要时更换它。

我是 WITH (NOLOCK) 的新手,所以这是我从这个有用的网站学到的东西:

WITH (NOLOCK) 表提示检索行,而无需等待其他正在读取或修改相同数据的查询来完成其处理。

理由

这些报价来自同一个链接。在每一项下,我都描述了我的想法,得出结论认为该行为不会影响我。

通常,经常使用显式表提示被认为是一种应避免的不良做法。特别是对于NOLOCK表提示,读取未提交的数据,读完后可能会回滚,会导致Dirty read,在未提交的数据读取过程中读取正在修改或删除的数据时会出现这种情况,从而导致数据你读到的可能会有所不同,或者甚至从未存在过。

脏读:我认为我不需要关心这个,因为 SELECT 实际上并不是因为脏读而无效。任何导致脏读的 DELETE 都会触发一个新的 SELECT 来纠正最终结果。 我认为两个 SELECT 结果都是有效的,尽管一个只在几毫秒内有效。

WITH (NOLOCK) 表提示也会导致不可重复读取;当需要多次读取相同的数据并且在这些读取过程中数据发生变化时,就会发生这种读取。在这种情况下,您将阅读同一行的多个版本。

不可重复读:我的 SELECT 只有该表中的一个 SELECT 语句,所以我认为这不是问题。 …

sql-server deadlock concurrency nolock

8
推荐指数
2
解决办法
1313
查看次数

考虑到处理缺点的方法,使用 NOLOCK 会出现哪些问题?

我正在研究使用 NOLOCK SQL 从一个活跃使用的数据库加载数据到报告数据库中的危害。我知道使用 NOLOCK 存在问题,但我正在考虑使用下面解释的策略来应对这些问题。

我知道有更好的方法,如日志传送、复制、镜像、AG、集群来拥有副本数据库,但这些不是这个问题的重点。

目标数据库有一个保存 LoadDate 的历史表。每 10 分钟,调度程序根据时间戳运行带有 WHERE 子句的 SELECT 查询(使用 NOLOCK)来获取数据,将其转储到临时表中,删除重复项(如果有)(保持最新)并将其合并到目标表中。

当 SELECT 查询运行时,SELECT 查询中使用的两个表可能会同时修改,但联接条件的列值不会更改。

伪代码示例:

DECLARE @LASTLOADDATE=SELECT MAX(LOADDATE) FROM HISTORYTABLE;
DECLARE @CURRENTDATE=GETDATE();

SELECT C1,C2,C3
FROM TBL1 T1 WITH(NOLOCK)
JOIN TBL2 T2 WITH(NOLOCK) ON T1.ID=T2.T1_ID
WHERE T1_TIMESTAMP>@LASTLOADDATE AND T1_TIMESTAMP<=@CURRENTDATE
//There is no index on timestamp column but an index may be added in the future

INSERT THE ABOVE RECORDS INTO STAGING TABLE
REMOVE DUPLICATES
MERGE DATA FROM STAGING TABLE INTO TARGET TABLE
INSERT INTO …
Run Code Online (Sandbox Code Playgroud)

sql-server concurrency isolation-level nolock

7
推荐指数
1
解决办法
2331
查看次数

With(NoLock) 对查询性能有帮助吗?

我们存储过程中的大多数 select 语句都使用它WITH(NOLOCK),我的同事告诉我,他们使用它来提高性能。现在,我知道这个提示有助于锁定,但它真的能提高性能吗?我在某处读到我们不应该使用NOLOCKOLTP 数据库中的提示,但我看到我的工作场所正在做相反的事情。有人可以阐明使用提示时的最佳实践吗NOLOCK?

sql-server-2012 nolock

7
推荐指数
1
解决办法
2614
查看次数