使用 NOLOCK 读取单个静态行。有啥害处?

Posted

技术标签:

【中文标题】使用 NOLOCK 读取单个静态行。有啥害处?【英文标题】:Using NOLOCK for reading single static row. Whats the harm?使用 NOLOCK 读取单个静态行。有什么害处? 【发布时间】:2014-10-03 14:46:52 【问题描述】:

有DEADLOCK经验的人可以赐教吗?

我读到它会导致日志文件损坏 - 这可能吗?我认为MS永远不会那样做。此外,如果像我这样的“某些情况”可以使用 DEADLOCK,为什么不使用它呢?

我没有数据集,返回表(就像 Stack Overflow 中的其他帖子一样)。我有一个 ID 为 select 的 SQL 语句,它只返回一行,例如:

 sqlstr = "SELECT Parameter1 FROM Companies WITH (NOLOCK) WHERE ID = 25

此外,此参数不会更改。但由于这是一个重负载的 aspnet 应用程序(不是网站),而且我一次又一次地运行这种查询,每次 SQL 读取都会导致 SQL 服务器锁定。如果可能的话,我宁愿避免这种情况。

本网站的每篇文章都与多条记录、记录集、脏读有关。我找不到任何有关“读取始终不变的单条记录”的信息。

请问有什么专家意见吗?

【问题讨论】:

如果您只读取一行,而ID 永远不会改变,为什么不创建过滤索引呢?然后,您将读取索引而不是表。 为什么不在应用程序中使用 SqlCacheDependency,这样它就不会对你的数据库造成太大影响? 有什么害处?有什么好处?如果该行是静态的,它可能无论如何都不会被锁定,并且如果页面不包含任何未提交的更改,SQL Server 也将跳过获取行级别 S 锁。 我看不出这里有任何死锁的原因。你真的看到他们了吗?至于你的问题,简而言之 - 你不需要这个提示,因为无论使用什么 TIL,读者都不会阻止其他读者。 【参考方案1】:

这个简单的select语句在默认事务隔离级别下没有任何lock/nolock提示执行时,会在该行上获得一个共享锁,这意味着其他用户也可以在该查询读取该行的同时读取该行。

另一方面,当您指定WITH (NOLOCK) 查询提示时,它根本不会获得任何锁。在这种情况下,其他用户也可以读取此行,但您可能正在读取脏行(尚未提交到磁盘且正在修改的数据)。

所以无论哪种情况,这个简单的选择都不会导致死锁。所以你真的应该问自己的问题是,用户是否能够看到脏数据?在大多数情况下,答案是否定的。

因此,不必担心此选择查询会出现死锁。只要您使用默认事务隔离级别。在更严格的隔离级别(如可序列化)中,选择可以锁定其他用户,但在默认隔离级别下应该没问题。

【讨论】:

如果使用索引和键查找,此选择可能会导致死锁。以与此查询相反的顺序写入锁。【参考方案2】:

NOLOCK 有两个主要缺点:它可以返回未提交的数据(您似乎并不担心),并且在极少数情况下会导致查询虚假失败。 NOLOCK 绝不会导致物理数据库损坏。

考虑对只读取数据的事务使用快照隔离。 SI 下的读者不会锁定或阻止。 SI 将它们从图片中移除。它为只读事务提供了完美的一致性。一定要了解缺点。

【讨论】:

【参考方案3】:

不值得。

NOLOCK 经常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。

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

错误或结果集可以为空、缺少行或多次显示同一行。

这是因为在您读取数据的同时其他事务正在移动数据。

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

还有其他副作用,这会导致牺牲您最初希望获得的速度提升。

现在你知道了,再也不要使用它了。

【讨论】:

【参考方案4】:

经过深入搜索并向许多专家提问后,我发现在这种情况下使用 NOLOCK 提示不会导致任何问题,但不建议这样做。 NOLOCK 没有问题,但是当我使用 sql2014 时,我“应该”使用 ISOLATION LEVEL 选项。它的一种方法来代替 NOLOCK。例如对于导致死锁的大表选择:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION; 
SELECT * FROM HugeTable;
COMMIT TRANSACTION;

非常方便。

我有 HugeTable 和一个使用 sqlAdapter 和 Radgrid 来显示这些数据的 Web 表单。每当我运行此报告时,虽然 radgrid 的索引和分页都很好,但它会导致死锁,这是有道理的。我把sqlAdapter的select语句改成了上面的语句,现在完美了。

最好的。

【讨论】:

以上是关于使用 NOLOCK 读取单个静态行。有啥害处?的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core:使用 NOLOCK 读取和选择记录

使用 WITH (NOLOCK) 和事务

转:nolock的替代方案-提交读快照隔离[行版本控制]

在异地托管图像有啥害处吗? [关闭]

在 C++ 中的单个输入行中读取整数列表

SQL Server 中WITH (NOLOCK)