在正在连接到自身的表上使用NOLOCK

时间:2014-08-26 21:37:44

标签: sql-server tsql nolock

我正在处理一个糟糕的视图,它在内部加入许多许多表,其中一些是同一个表。

我想知道,当一个表加入自身时,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

3 个答案:

答案 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