3

我正在使用一个糟糕的视图,它在内部将许多很多表连接在一起,其中一些是同一张表。

我想知道,当一个表被连接到自身时,NOLOCK如果它在一个连接上而不是另一个连接上,如何解释提示?是否NOLOCK仍然对表有效,或者如果NOLOCK不包含在同一个表的连接之一中,表是否完全锁定?

例如(这是伪代码,假设存在有效JOIN ON条件):

SELECT *
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK)
JOIN Table2_Table2 tt (NOLOCK)
JOIN Table2 t22 (NOLOCK)
JOIN Table1 t11

是否Table1被锁定或保持NOLOCK编辑?

4

3 回答 3

1

是的,它确实被最后一次Table1 t11通话锁定了。每个表锁定提示都应用于特定的引用。如果您仅将其应用于仅用于该引用的表引用之一,则其他表引用将具有自己的单独锁定设置。您可以使用BEGIN TRANSACTION并执行两个不同的查询来测试它。

查询 1(锁定表)故意注释掉COMMIT TRANSACTION

BEGIN TRANSACTION
SELECT *
FROM Table1 WITH (TABLOCK)
-- COMMIT TRANSACTION

由于COMMIT TRANSACTION被注释掉,事务没有关闭,仍然会持有锁。当第二个查询运行时,第一个锁仍将应用于第一个查询的表。

查询 2(此查询将挂起,因为第一个锁将阻塞Table1 t11

BEGIN TRANSACTION
SELECT *
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK)
JOIN Table2_Table2 tt (NOLOCK)
JOIN Table2 t22 (NOLOCK)
JOIN Table1 t11
COMMIT TRANSACTION
于 2014-08-26T22:29:20.380 回答
0

我猜想不使用 nolock 会导致某种类型的锁定,无论它是否在查询中的其他地方使用 nolock 连接。所以它可能会导致行锁,所以将 nolock 放在缺少它的连接旁边。

于 2014-08-26T22:13:53.123 回答
0

用非常简单的术语,可以这样想:您在查询中引用的每个表都会导致物理执行计划运算符访问该表。表格提示适用于该运算符。这意味着您可以对同一个表使用混合锁定提示。您请求的锁定行为将应用于该特定运算符碰巧读取的那些行。相应的操作员可能会扫描一个表,或扫描一系列行,或读取单行。不管它是什么,它都是在指定的锁定选项下执行的。

查看查询的执行计划以查找各个运算符。

于 2014-08-26T22:20:46.093 回答