SQLServerNOLOCK 和连接

背景: 我想运行一个性能关键的查询,我不关心脏读操作。

我的问题是: 如果我使用连接,是否也必须指定这些连接上的 NOLOCK 提示?

例如; 是:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

相当于:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

还是需要在连接上指定 (NOLOCK)提示以确保不锁定已连接的表?

231739 次浏览

我非常确定您需要为查询中的每个 JOIN指定 NOLOCK。但我的经验仅限于 SQLServer2005。

当我查找 MSDN 只是为了确认,我找不到任何确切的东西。下面的陈述似乎让我认为,就2008年而言,你的上述两个陈述是相同的,但就2005年而言,情况并非如此:

[ SQLServer2008R2]

所有锁提示都传播到 由查询计划访问的所有表和视图,包括视图中引用的表和视图。此外,SQLServer 还执行相应的锁一致性检查。

[ SQLServer2005]

在 SQLServer2005中,所有锁提示都会传播到视图中引用的所有表和视图。此外,SQLServer 还执行相应的锁一致性检查。

此外,值得注意的是,2005年和2008年的情况都是如此:

如果查询计划不访问表,则忽略表提示。这可能是由于优化器选择根本不访问表,或者是由于访问的是索引视图。在后一种情况下,可以通过使用 OPTION (EXPAND VIEWS)查询提示来阻止访问索引视图。

都不是。您将隔离级别设置为 READ UNCOMMITTED,这总是比给出单独的锁提示要好。或者,更好的是,如果您关心像 一致性这样的细节,那么使用 快照隔离

我不会回答 READ UNCOMMITTED的论点,只回答你最初的问题。

是的,您需要在联接的每个表上使用 WITH(NOLOCK)。不,您的查询是不同的。

试试这个练习。开始一个事务并向 table1和 table2插入一行。还不要提交或回滚事务。此时,第一个查询将成功返回并包含未提交的行; 第二个查询将不会返回,因为 table2上没有 WITH(NOLOCK)提示。