【发布时间】:2010-09-17 15:11:20
【问题描述】:
我想真正的问题是:
如果我不关心脏读,在 SELECT 语句中添加 with (NOLOCK) 提示会影响:
- 当前的 SELECT 语句
- 针对给定表的其他事务
例子:
Select *
from aTable with (NOLOCK)
【问题讨论】:
标签: sql sql-server locking
我想真正的问题是:
如果我不关心脏读,在 SELECT 语句中添加 with (NOLOCK) 提示会影响:
例子:
Select *
from aTable with (NOLOCK)
【问题讨论】:
标签: sql sql-server locking
如果查询一次运行多次,答案是是,因为每个事务不需要等待其他事务完成。但是,如果查询单独运行一次,则答案是否定的。
是的。仔细使用 WITH(NOLOCK) 很有可能会整体加快数据库速度。这意味着其他事务不必等待此 SELECT 语句完成,但另一方面,其他事务将减慢速度,因为它们现在与新事务共享其处理时间。
注意仅在具有聚集索引的表的 SELECT 语句中使用WITH (NOLOCK)。
WITH(NOLOCK) 通常被用作加速数据库读取事务的神奇方式。
结果集可以包含尚未提交的行,这些行通常稍后会回滚。
如果将 WITH(NOLOCK) 应用于具有非聚集索引的表,则当行数据流式传输到结果表时,其他事务可以更改行索引。这意味着结果集可能会丢失行或多次显示同一行。
READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。
【讨论】:
1) 是的,带有NOLOCK 的选择将比普通选择更快地完成。
2) 是的,带有NOLOCK 的选择将允许针对受影响表的其他查询比正常选择更快地完成。
为什么会这样?
NOLOCK 通常(取决于您的数据库引擎)意味着给我您的数据,我不在乎它处于什么状态,并且在您读取它时不要打扰它。它同时速度更快,资源消耗更少,而且非常非常危险。
您应该被警告永远不要更新或执行任何系统关键操作,或者使用源自NOLOCK 读取的数据需要绝对正确性的地方。此数据绝对有可能包含在查询运行期间已删除的行或在尚未完成的其他会话中已删除的行。此数据可能包含已部分更新的行。此数据可能包含违反外键约束的记录。此数据可能会排除已添加到表中但尚未提交的行。
你真的无法知道数据的状态是什么。
如果您尝试获取诸如行计数或其他可以接受一些误差范围的汇总数据,那么NOLOCK 是提高这些查询的性能并避免它们对数据库性能产生负面影响的好方法。
始终谨慎使用NOLOCK 提示,并对它返回的任何可疑数据进行处理。
【讨论】:
除了上面所说的之外,您应该非常清楚 nolock 实际上会给您带来不获取在选择之前提交的行的风险。
【讨论】:
NOLOCK 使大多数 SELECT 语句更快,因为缺少共享锁。此外,没有发布锁意味着写入器不会受到您的 SELECT 的阻碍。
NOLOCK 在功能上等同于 READ UNCOMMITTED 隔离级别。主要区别在于,如果您愿意,您可以在某些表上使用 NOLOCK,但不能在其他表上使用。如果您计划对复杂查询中的所有表使用 NOLOCK,那么使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 会更容易,因为您不必将提示应用于每个表。
这里是有关您可以使用的所有隔离级别的信息,以及表格提示。
【讨论】:
它会更快,因为它不必等待锁
【讨论】: