关于这个问题我想问
比较两个查询:
(1)
DELETE dbA.dbo.tableA
FROM dbA.dbo.tableA a WITH(NOLOCK)
JOIN dbB.dbo.tableB b WITH(NOLOCK)
ON
b.colA = a.colA
AND b.colB = a.colB
和
(2)
DELETE FROM dbA.dbo.tableA
WHERE EXISTS
(
SELECT *
FROM dbB.dbo.tableB b WITH(NOLOCK)
where
b.colA = dbA.dbo.tableA .colA
AND b.colB = dbA.dbo.tableA .colB
)
很明显,如果我们不考虑可能导致脏读的并发写入,查询会做类似的工作。
但我有疑问
我对以下评论是否正确?
请注意,将从语句 (2) 的最开始放置一个共享(可升级?)锁 @ tableA,而不是在连接 (1) 中放置两个 NOLOCK 表,这将放置第一个锁 - UX 锁仅在此之后将找到要删除的第一行
不。
至少在我的测试中,它们都具有相同的执行计划和相同的锁定行为。两者都立即放置一个
IX
锁tableA
和一个模式稳定性锁TableB
,然后在进行聚簇索引扫描时遵循相同的行为,在页面上TableA
获取IU
锁,U
锁上key
,然后在匹配的情况下将页面锁转换为IX
然后键锁定到X
删除行之前。NOLOCK
这与完全删除提示的模式完全相同,tableA
因此在这种情况下毫无意义。我的原始结果在两个查询之间存在一些差异,因为 Join 版本有一系列明显的获取和立即释放模式稳定性锁,但在该版本
TableA
中没有出现。EXISTS
这似乎与 SSMS 中是否启用了“包括实际执行计划”选项有关。今天,如果我启用了这个选项,这个系列就会出现在他们两个的锁定信息中,所以不确定为什么最初它只出现在一个中。也许一些时间问题。您可以使用如下方式查看此锁定信息
TF1200
(禁用“包括实际执行计划”选项)。代码
ObjectIds
锁定资源
输出(所有三个查询)