谁能解释一下在查询中使用with (nolock)的含义,什么时候应该/不应该使用它?

例如,如果你有一个银行应用程序,有很高的事务率,在某些表中有很多数据,在什么类型的查询中nolock是可以的?在某些情况下,你是否应该总是使用它/永远不要使用它?


当前回答

不确定为什么没有在数据库事务中包装金融事务(当您将资金从一个帐户转移到另一个帐户时—您不每次提交事务的一方—这就是显式事务存在的原因)。即使您的代码听起来对业务事务来说是脑死亡,但所有事务性数据库都有可能在发生错误或失败时执行隐式回滚。我觉得这个讨论超出了你的理解力。

如果您遇到了锁定问题,请实现版本控制并清理代码。

没有锁不仅返回错误的值,还返回虚记录和副本。

这是一个常见的误解,它总是使查询运行得更快。如果表上没有写锁,也没有什么区别。如果表上有锁,它可能会使查询更快,但最初发明锁是有原因的。

公平地说,这里有两个特殊的场景,nolock提示可以提供实用程序

1) 2005年以前的sql server数据库需要对实时OLTP数据库运行长查询,这可能是唯一的方法

2)写得很糟糕的应用程序,它锁定记录并将控制权返回给UI和阅读器,无限期地阻塞。如果应用程序无法修复(第三方等),数据库是2005年以前或版本无法打开,Nolock可以在这里提供帮助。

其他回答

不幸的是,这不仅仅是读取未提交的数据。在后台,您可能会读两次页面(在页面分割的情况下),或者您可能会完全错过这些页面。所以你的结果可能是严重扭曲的。

看看Itzik Ben-Gan的文章。以下是节选:

" With the NOLOCK hint (or setting the isolation level of the session to READ UNCOMMITTED) you tell SQL Server that you don't expect consistency, so there are no guarantees. Bear in mind though that "inconsistent data" does not only mean that you might see uncommitted changes that were later rolled back, or data changes in an intermediate state of the transaction. It also means that in a simple query that scans all table/index data SQL Server may lose the scan position, or you might end up getting the same row twice. "

问题是什么更糟:

死锁,或者 一个错误的值?

对于金融数据库来说,死锁比错误的值更糟糕。我知道这听起来有点反,但听我说完。DB事务的传统示例是更新两行,从一行中减去一行,向另一行中添加一行。这是错误的。

在财务数据库中使用业务事务。这意味着为每个帐户添加一行。这些事务的完成和行的成功写入是极其重要的。

让账户余额暂时错误不是什么大问题,这就是一天结束的和解。由于同时使用两台atm机,比未从数据库中读取数据更有可能发生帐户透支。

也就是说,SQL Server 2005修复了大部分使NOLOCK成为必要的错误。因此,除非您使用的是SQL Server 2000或更早版本,否则不需要它。

进一步的阅读 行级版本控制

当你可以接受“脏”数据时使用nolock。这意味着nolock也可以读取正在修改的数据和/或未提交的数据。

在高事务处理环境中使用它通常不是一个好主意,这就是为什么它不是查询的默认选项。

WITH (NOLOCK)相当于使用READ uncommitted作为事务隔离级别。因此,您可能会读取一个未提交的行,该行随后会被回滚,即从未进入数据库的数据。因此,虽然它可以防止读取被其他操作死锁,但也存在风险。在具有高交易率的银行应用程序中,它可能不是您试图用它解决的任何问题的正确解决方案。

不确定为什么没有在数据库事务中包装金融事务(当您将资金从一个帐户转移到另一个帐户时—您不每次提交事务的一方—这就是显式事务存在的原因)。即使您的代码听起来对业务事务来说是脑死亡,但所有事务性数据库都有可能在发生错误或失败时执行隐式回滚。我觉得这个讨论超出了你的理解力。

如果您遇到了锁定问题,请实现版本控制并清理代码。

没有锁不仅返回错误的值,还返回虚记录和副本。

这是一个常见的误解,它总是使查询运行得更快。如果表上没有写锁,也没有什么区别。如果表上有锁,它可能会使查询更快,但最初发明锁是有原因的。

公平地说,这里有两个特殊的场景,nolock提示可以提供实用程序

1) 2005年以前的sql server数据库需要对实时OLTP数据库运行长查询,这可能是唯一的方法

2)写得很糟糕的应用程序,它锁定记录并将控制权返回给UI和阅读器,无限期地阻塞。如果应用程序无法修复(第三方等),数据库是2005年以前或版本无法打开,Nolock可以在这里提供帮助。