SELECT 语句中 NOLOCK 提示的效果

问题描述 投票:0回答:5

我想真正的问题是:

如果我不关心脏读,在 SELECT 语句中添加 with (NOLOCK) 提示会影响以下性能:

  1. 当前 SELECT 语句
  2. 针对给定表的其他事务

示例:

Select * 
from aTable with (NOLOCK)
sql sql-server locking
5个回答
313
投票

1) ,使用

NOLOCK
进行选择将比普通选择更快完成。

2) ,使用

NOLOCK
的选择将允许针对受影响表的其他查询比正常选择更快地完成。

为什么会这样?

NOLOCK
通常(取决于您的数据库引擎)意味着给我您的数据,我不在乎它处于什么状态,并且在您读取数据时不必费心保持它不动。它的速度更快,资源消耗更少,而且非常非常危险。

您应该被警告不要进行更新或执行任何系统关键操作,或者在需要绝对正确性的情况下使用源自

NOLOCK
读取的数据。此数据绝对有可能包含在查询运行期间删除的行或已在其他尚未最终确定的会话中删除的行。该数据可能包含已部分更新的行。该数据可能包含违反外键约束的记录。该数据可能不包括已添加到表中但尚未提交的行。

你真的没有办法知道数据的状态是什么。

如果您尝试获取行计数或其他可以接受一定误差范围的摘要数据等内容,那么

NOLOCK
是提高这些查询性能并避免它们对数据库性能产生负面影响的好方法。

始终谨慎使用

NOLOCK
提示,并可疑地对待它返回的任何数据。


65
投票

NOLOCK 使大多数 SELECT 语句更快,因为缺少共享锁。此外,不发出锁意味着写入者不会受到 SELECT 的阻碍。

NOLOCK 在功能上相当于 READ UNCOMMITTED 隔离级别。主要区别在于,如果您选择的话,您可以在某些表上使用 NOLOCK,但不能在其他表上使用 NOLOCK。如果您计划在复杂查询中的所有表上使用 NOLOCK,那么使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 会更容易,因为您不必将提示应用于每个表。

以下是有关您可以使用的所有隔离级别的信息以及表格提示。

设置事务隔离级别

表提示 (Transact-SQL)


14
投票

除了上面所说的之外,您应该非常清楚,nolock 实际上会带来风险,即您无法获取在选择之前已提交的行。

请参阅

http://blogs.msdn.com/sqlcat/archive/2007/02/01/previously-comfilled-rows-might-be-missed-if-nolock-hint-is-used.aspx


7
投票
会更快,因为不需要等待锁。


2
投票
  • 如果查询一次运行多次,答案是

    ,因为每个事务不需要等待其他事务完成。但是,如果查询单独运行一次,那么答案是否定的。

  • 是的。仔细使用WITH(NOLOCK) 很有可能会提高数据库的整体速度。这意味着其他事务不必等待此 SELECT 语句完成,但另一方面,其他事务会减慢速度,因为它们现在与新事务共享处理时间。

请小心

在具有聚集索引的表的 SELECT 语句中使用WITH (NOLOCK)

WITH(NOLOCK) 经常被用作加速数据库读取事务的神奇方法。

结果集可以包含尚未提交的行,这些行通常稍后会回滚。

如果将WITH(NOLOCK)应用于具有非聚集索引的表,则当行数据流入结果表时,其他事务可以更改行索引。这意味着结果集可能会缺少行或多次显示同一行。

READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格时,单列中的数据会被损坏。

© www.soinside.com 2019 - 2024. All rights reserved.