SQL Server NOLOCK和连接

Dan*_*anP 140 sql sql-server nolock

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

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

例如; 是:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID
Run Code Online (Sandbox Code Playgroud)

相当于:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID
Run Code Online (Sandbox Code Playgroud)

或者我是否需要(NOLOCK)在连接上指定提示以确保我没有锁定连接表?

cod*_*ion 152

我不会解决这个READ UNCOMMITTED论点,只是你原来的问题.

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

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

  • 使用 SQL Server 2016 可以确认情况仍然如此。 (3认同)

Jag*_*mag 17

我非常确定您需要在查询中指定NOLOCKfor each 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)查询提示来防止访问索引视图.

  • @InSane:你从哪里得到这些信息?这似乎违背了公认的答案. (2认同)
  • 2005年的文字谈到了VIEWS。因此,如果您“从myview with(nolock)开始”,则表示nolock会传播到myview涉及的所有表和视图中(在那里可能有10个联接)。不确定2008文本的确切含义是什么,因为它在视图之外还添加了“由查询计划访问”。 (2认同)

Rem*_*anu 9

都不是.您将隔离级别设置READ UNCOMMITTED为始终优于提供单独的锁定提示.或者,更好的是,如果您关心一致性等细节,请使用快照隔离.

  • 但你考虑过快照隔离吗?`ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;`.结果非常引人注目,因为所有正常的读取提交读取都会变成快照读取,无锁定且一致.成本增加`tempdb`负载:http://msdn.microsoft.com/en-us/library/ms175492.aspx (2认同)