SQL Server NOLOCK和连接

时间:2010-09-24 01:02:44

标签: sql sql-server nolock

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

我的问题是;如果我正在使用连接,我是否必须在那些上指定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)提示以确保我没有锁定已连接的表?

3 个答案:

答案 0 :(得分:142)

我不会解决READ UNCOMMITTED论证,只讨论原始问题。

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

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

答案 1 :(得分:16)

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

当我查询MSDN以确认时,我找不到任何确定的内容。以下陈述似乎让我想到,对于2008年,你上面的两个陈述是相同的,尽管2005年并非如此:

  

[SQL Server 2008 R2]

     

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

     

[SQL Server 2005]

     

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

此外,请注意 - 这适用于2005年和2008年:

  

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

答案 2 :(得分:9)

都不是。您将隔离级别设置为READ UNCOMMITTED,这总是比提供单独的锁定提示更好。或者,更好的是,如果您关心consistency等详细信息,请使用snapshot isolation