我正在处理一个糟糕的视图,它在内部加入许多许多表,其中一些是同一个表。
我想知道,当一个表加入自身时,NOLOCK
提示如何解释它是否在其中一个连接而不是另一个连接上? NOLOCK
是否仍对表有效,或者如果NOLOCK
未包含在同一个表的某个联接中,则表是否完全被锁定?
例如(这是pseduo-code,假设有有效的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
?
答案 0 :(得分:0)
我猜想不使用nolock会导致某种类型的锁定,无论它是否在nolock查询的其他地方加入。因此,它可能导致行锁定,因此将nolock放在缺少它的连接旁边。
答案 1 :(得分:0)
简单来说,可以这样想:您在查询中引用的每个表都会导致物理执行计划操作员访问该表。表提示适用于该运算符。这意味着您可以为同一个表提供混合锁定提示。您请求的锁定行为将应用于此特定操作符恰好读取的行。相应的操作员可能扫描表,或扫描一系列行,或读取单行。无论是什么,它都是在指定的锁定选项下执行的。
查看查询的执行计划以查找各个运算符。
答案 2 :(得分:0)
是的,它确实被上一次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