with (nolock)
在您应该/不应该使用查询时,有人可以解释使用查询的含义吗?
例如,如果您有一个银行业务应用程序,该应用程序具有高事务处理率,并且某些表中的数据很多,那么在哪种类型的查询中就可以了?在某些情况下,您应该始终使用它/从不使用它吗?
with (nolock)
在您应该/不应该使用查询时,有人可以解释使用查询的含义吗?
例如,如果您有一个银行业务应用程序,该应用程序具有高事务处理率,并且某些表中的数据很多,那么在哪种类型的查询中就可以了?在某些情况下,您应该始终使用它/从不使用它吗?
Answers:
WITH(NOLOCK)等同于使用READ UNCOMMITED作为事务隔离级别。因此,您将冒着读取未提交的行并随后回滚的风险,即从未进入数据库的数据。因此,尽管它可以防止读取因其他操作而陷入僵局,但它存在风险。在具有高事务处理率的银行应用程序中,它可能不是您要尝试使用IMHO解决的任何问题的正确解决方案。
NOLOCK
与a一起使用,SELECT
如果在进行选择时曾经将数据插入(或更新)到表中,则冒着多次返回相同行(重复数据)的风险。
问题是更糟的是:
对于财务数据库,僵局要比错误的值严重得多。我知道这听起来很倒霉,但请听我说。DB事务的传统示例是更新两行,从两行中减去然后加到另一行。那是错的。
在财务数据库中,您使用业务交易。这意味着向每个帐户添加一行。这些事务完成并且行被成功写入是至关重要的。
暂时使帐户余额有误不是什么大不了的事情,这就是日对帐的目的。由于一次使用两个ATM而不是从数据库中未提交读操作,导致帐户透支的可能性更大。
也就是说,SQL Server 2005修复了大多数NOLOCK
必要的错误。因此,除非您使用的是SQL Server 2000或更早版本,否则就不需要它。
进一步阅读
行级版本控制
不幸的是,这不仅仅是读取未提交的数据。在后台,您可能会阅读两次页面(在分页的情况下),或者您可能会完全错过这些页面。因此,您的结果可能会严重偏斜。
查看Itzik Ben-Gan的文章。摘录如下:
“使用NOLOCK提示(或将会话的隔离级别设置为READ UNCOMMITTED),您告诉SQL Server您不希望保持一致性,因此无法保证。请记住,尽管“不一致的数据”不仅意味着您可能会看到未提交的更改随后被回滚,或者数据更改处于事务的中间状态,这也意味着在扫描所有表/索引数据的简单查询中,SQL Server可能会丢失扫描位置,或者最终两次获得同一行。“
不知道为什么不将金融交易包装在数据库交易中(例如,当您将资金从一个帐户转移到另一个帐户时-您一次不承诺交易的一方-这就是存在显式交易的原因)。即使您的代码听上去很像商务事务的头脑,但所有的交易数据库都有可能在发生错误或失败时进行隐式回滚。我认为这种讨论很麻烦。
如果遇到锁定问题,请实施版本控制并清理代码。
没有锁不仅会返回错误的值,还会返回幻像记录和重复项。
一个普遍的误解是,它总是会使查询运行得更快。如果表上没有写锁,则没有任何区别。如果表上有锁,则可以使查询更快,但是首先要发明锁是有原因的。
公平地说,以下是两种特殊情况,其中nolock提示可能会提供实用程序
1)需要对实时OLTP数据库运行长时间查询的2005年前的sql server数据库,这可能是唯一的方法
2)编写不良的应用程序会锁定记录并将控制权返回给UI,并且读者将被无限期地阻止。如果无法修复应用程序(第三方等)并且数据库为2005年前版本或无法打开版本控制,则Nolock在这里可能会有所帮助。
NOLOCK
等价于READ UNCOMMITTED
,但是Microsoft说您不应将其用于UPDATE
或DELETE
声明:
对于UPDATE或DELETE语句:将来的Microsoft SQL Server版本将删除此功能。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。
http://msdn.microsoft.com/en-us/library/ms187373.aspx
本文适用于SQL Server 2005,因此,NOLOCK
如果您使用的是该版本,则支持该版本。为了使您的代码更适合将来(假设您已决定使用脏读取),可以在存储过程中使用此代码:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
您可以在仅读取数据时使用它,而不必担心是否会取回尚未提交的数据。
读取操作可能会更快,但我无法真正说出多少。
通常,我建议不要使用它-读取未提交的数据充其量可能会使您感到困惑。
通常还可以的另一种情况是在报表数据库中,该数据库中的数据可能已经老化,并且写不会发生。但是,在这种情况下,应由管理员通过更改默认隔离级别在数据库或表级别设置该选项。
在一般情况下:您可以在非常确定可以读取旧数据时使用它。要记住的重要一点是,很容易出错。例如,即使在编写查询时还可以,但您确定将来数据库中不会发生某些更改以使这些更新更加重要吗?
我还将提出第二种观点,即在银行应用程序中这可能不是一个好主意。或库存应用。或任何您正在考虑交易的地方。
简短答案:
仅WITH (NOLOCK)
在具有聚集索引的表上使用SELECT语句。
长答案:
WITH(NOLOCK)通常被用作提高数据库读取速度的一种神奇方法。
结果集可以包含尚未提交的行,这些行通常在以后回滚。
如果将WITH(NOLOCK)应用于具有非聚集索引的表,则在将行数据流式传输到结果表时,其他事务可以更改行索引。这意味着结果集可能缺少行或多次显示同一行。
READ COMMITTED(读取已提交)增加了一个额外的问题,即数据在单个列中损坏,多个用户同时更改了同一单元格。
READ UNCOMITTED
将完全不受影响。有一个原因将其包含在ANSI标准中。
我的2美分- WITH (NOLOCK
在需要生成报告时可以使用)。此时,数据不会有太大变化,并且您也不想锁定这些记录。
我曾经检索过“下一批”要做的事情。在这种情况下,哪个项目是没有关系的,并且我有很多用户在运行相同的查询。
当您对“脏”数据没问题时,请使用nolock。这意味着nolock也可以读取正在修改的数据和/或未提交的数据。
在高事务环境中使用它通常不是一个好主意,这就是为什么它不是查询的默认选项。
我使用(nolock)提示,特别是在活动频繁的SQLServer 2000数据库中。我不确定在SQL Server 2005中是否需要它。我最近应客户端DBA的请求在SQL Server 2000中添加了该提示,因为他注意到了很多SPID记录锁。
我只能说,使用提示并没有伤害我们,似乎使锁定问题得以解决。那个特定客户的DBA基本上坚持我们使用提示。
顺便说一句,我处理的数据库是企业医疗索赔系统的后端,因此我们在许多联接中谈论数百万条记录和20多个表。我通常为联接中的每个表添加一个WITH(nolock)提示(除非它是派生表,在这种情况下,您不能使用该特定提示)