小编tra*_*ark的帖子

在这种情况下使用 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
查看次数

标签 统计

concurrency ×1

deadlock ×1

nolock ×1

sql-server ×1