使用 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 读取单个静态行。有啥害处?的主要内容,如果未能解决你的问题,请参考以下文章