在事务中或删除表时使用“with nolock”

Posted

技术标签:

【中文标题】在事务中或删除表时使用“with nolock”【英文标题】:using 'with nolock' in transaction or when dropping table 【发布时间】:2019-07-17 09:22:36 【问题描述】:

我正在尝试清理临时表。最快的方法是删除或截断表然后回滚并且只包含所需的行。 现在我的问题是数据库的“死锁”。有没有办法使用'with nolock'让数据库不锁定

BEGIN TRANSACTION;
drop table audit.Testing with (nolock) ;

rollback transaction

 SELECT *
 from
 (select *
 ,rn = ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Id DESC)
  FROM audit.testing with (nolock)
  ) a
   where rn =1
  order by Id, SysEndTime desc```

【问题讨论】:

【参考方案1】:

您处于死锁状态,因为 WITH (NOLOCK) 相当于使用 READ UNCOMMITTED READUNCOMMITTED 指定允许脏读。不发布共享锁来防止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻止当前事务读取锁定的数据。允许脏读可能会导致更高的并发性,但代价是读取数据修改,然后由其他事务回滚。这可能会为您的事务产生错误,向用户显示从未提交的数据,或导致用户看到两次(或根本看不到)记录。

READUNCOMMITTED 和 NOLOCK 提示仅适用于数据锁。所有查询,包括带有 READUNCOMMITTED 和 NOLOCK 提示的查询,都会在编译和执行期间获取 Sch-S(模式稳定性)锁。因此,当并发​​事务在表上持有 Sch-M(模式修改)锁时,查询会被阻止。例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。任何并发查询,包括使用 READUNCOMMITTED 或 NOLOCK 提示运行的查询,在尝试获取 Sch-S 锁时都会被阻止。相反,持有 Sch-S 锁的查询会阻塞试图获取 Sch-M 锁的并发事务 microsoft docs

【讨论】:

明白。还有一个问题。如果我删除一个表并回滚,那么只包含我想要的行。但是表有几百万行,查询是否需要很长时间才能完成

以上是关于在事务中或删除表时使用“with nolock”的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中WITH (NOLOCK)

关于sql中的with(nolock)

转:nolock的替代方案-提交读快照隔离[行版本控制]

在 JOIN 查询中的某些表上使用 WITH (NOLOCK)

给 EF Core 查询增加 With NoLock

MySQL误删数据救命指南