247

用通俗易懂的英语,使用的优缺点是什么

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

在 .NET 应用程序和报告服务应用程序的查询中?

4

10 回答 10

234

此隔离级别允许脏读。一个事务可能会看到其他事务所做的未提交更改。

为了保持最高级别的隔离,DBMS 通常会在数据上获取锁,这可能会导致并发丢失和高锁定开销。此隔离级别放宽了此属性。

您可能需要查看Wikipedia 文章以READ UNCOMMITTED获取一些示例和进一步阅读。


您可能也有兴趣查看 Jeff Atwood 的博客文章,了解他和他的团队如何在 Stack Overflow 早期解决死锁问题。根据杰夫的说法:

但是nolock危险吗?你最终能用 on 读取无效数据read uncommitted吗?是的,理论上。你会发现不乏数据库架构宇航员,他们开始向你扔 ACID 科学,当你告诉他们你想尝试时,他们几乎拉响了建筑物的火警nolock。这是真的:这个理论很可怕。但我的想法是:“理论上,理论与实践没有区别。实践中是有区别的。”

我永远不会建议将nolock “对你有什么问题”作为一般的“对你有什么好处”的蛇油修复您可能遇到的任何数据库死锁问题。您应该首先尝试诊断问题的根源。

但是在实践中,添加nolock到您绝对知道的简单、直接的只读事务中的查询似乎永远不会导致问题……只要您知道自己在做什么。

READ UNCOMMITTED您可能要考虑的级别的另一种选择是READ COMMITTED SNAPSHOT. 再次引用杰夫:

快照依赖于一种全新的数据更改跟踪方法……不仅仅是轻微的逻辑更改,它还需要服务器以不同的物理方式处理数据。一旦启用了这种新的数据更改跟踪方法,它就会创建每个数据更改的副本或快照。通过在争用时读取这些快照而不是实时数据,读取时不再需要共享锁,并且整体数据库性能可能会提高。

于 2010-03-18T15:35:52.660 回答
51

我最喜欢的用例read uncommited是调试事务中发生的事情。

在调试器下启动您的软件,当您单步执行代码行时,它会打开一个事务并修改您的数据库。当代码停止时,您可以打开查询分析器,设置读取未提交的隔离级别并进行查询以查看发生了什么。

您还可以使用它来查看长时间运行的过程是否卡住或使用带有count(*).

如果您的公司喜欢制作过于复杂的存储过程,那就太好了。

于 2013-08-23T21:01:30.180 回答
43

这对于查看长插入查询的进度、进行任何粗略估计(如COUNT(*)或粗略SUM(*))等很有用。

换句话说,脏读查询返回的结果很好,只要您将它们视为估计并且不根据它们做出任何关键决策。

于 2010-03-18T16:04:23.177 回答
25

优点是在某些情况下它可以更快。缺点是结果可能是错误的(尚未提交的数据可能会被返回)并且不能保证结果是可重复的。

如果您关心准确性,请不要使用它。

更多信息在MSDN上:

实现脏读或隔离级别 0 锁定,这意味着不会发出共享锁,也不会使用排他锁。设置此选项时,可以读取未提交或脏数据;数据中的值可以更改,并且行可以在事务结束之前在数据集中出现或消失。此选项与在事务中的所有 SELECT 语句中的所有表上设置 NOLOCK 具有相同的效果。这是四个隔离级别中限制最少的。

于 2010-03-18T15:32:52.070 回答
17

什么时候可以使用READ UNCOMMITTED

经验法则

:显示不断变化的总数的大汇总报告。

风险:几乎所有其他。

好消息是,大多数只读报告都属于“良好”类别。

更多详情...

可以使用它:

  • 几乎所有面向用户的当前非静态数据汇总报告,例如年初至今的销售额。它存在误差范围(可能 < 0.1%),该误差范围远低于其他不确定因素,例如输入误差或只是精确数据何时逐分钟记录的随机性。

这可能涵盖了商业智能部门在 SSRS 中所做的大部分工作。当然,前面有 $ 符号的东西除外。许多人对金钱的计算比应用于服务客户和产生金钱所需的相关核心指标要热情得多。(我责怪会计师)。

有风险时

  • 任何细化到详细级别的报告。如果需要该详细信息,则通常意味着每一行都与决策相关。事实上,如果你不能在不阻塞的情况下拉出一个小子集,那可能是因为它当前正在被编辑。

  • 历史数据。它很少会产生实际的差异,但尽管用户明白不断变化的数据不可能完美,但他们对静态数据的感觉却不尽相同。脏读在这里不会受到伤害,但偶尔会出现双重阅读。既然您不应该在静态数据上设置块,为什么要冒险呢?

  • 几乎任何为应用程序提供数据的东西都具有写入功能。

当即使是好的场景也不行。

  • 是否有任何应用程序或更新流程使用大单笔交易?删除然后重新插入您要报告的大量记录的那些?在那种情况下,你真的不能NOLOCK在这些桌子上使用任何东西。
于 2014-11-19T16:58:35.283 回答
7

关于报告,我们在所有报告查询中使用它,以防止查询陷入数据库。我们可以这样做,因为我们正在提取历史数据,而不是精确到微秒的数据。

于 2013-09-28T19:44:14.317 回答
5

在源极不可能更改的情况下使用 READ_UNCOMMITTED。

  • 读取历史数据时。例如两天前发生的一些部署日志。
  • 再次读取元数据时。例如基于元数据的应用程序。

当您知道在 fetch 操作期间 souce 可能发生变化时,不要使用 READ_UNCOMMITTED。

于 2013-09-23T17:19:20.297 回答
2

这会给您带来脏读,并向您显示尚未提交的事务。这是最明显的答案。我认为仅仅为了加快阅读速度而使用它并不是一个好主意。如果您使用良好的数据库设计,还有其他方法可以做到这一点。

注意到没有发生的事情也很有趣。READ UNCOMMITTED 不仅忽略其他表锁。它本身也不会导致任何锁定。

假设您正在生成一个大型报告,或者您正在使用大型且可能复杂的 SELECT 语句将数据迁移出数据库。这将导致在事务期间可能升级为共享表锁的共享锁。其他事务可以从表中读取,但无法更新。如果它是一个生产数据库,这可能不是一个好主意,因为生产可能会完全停止。

如果您使用的是 READ UNCOMMITTED,您将不会在表上设置共享锁。您可能会从一些新事务中获得结果,或者您可能不依赖于数据插入表的位置以及您的 SELECT 事务读取了多长时间。例如,如果发生页面拆分(数据将被复制到数据文件中的另一个位置),您也可能会获得两次相同的数据。

因此,如果在执行 SELECT 时可以插入数据对您来说非常重要,那么 READ UNCOMMITTED 可能是有意义的。您必须考虑到您的报告可能包含一些错误,但如果它基于数百万行并且在选择结果时只有少数行被更新,这可能“足够好”。您的事务也可能一起失败,因为可能无法保证行的唯一性。

更好的方法可能是使用 SNAPSHOT ISOLATION LEVEL,但您的应用程序可能需要一些调整才能使用它。例如,如果您的应用程序对一行进行了排他锁以防止其他人读取它并进入 UI 中的编辑模式。SNAPSHOT ISOLATION LEVEL 也会带来相当大的性能损失(尤其是在磁盘上)。但是你可以通过在问题上投入硬件来克服这个问题。:)

您还可以考虑恢复数据库的备份以用于报告数据或将数据加载到数据仓库中。

于 2013-05-10T07:14:03.347 回答
0

它可以用于一个简单的表,例如在一个只插入的审计表中,其中没有对现有行的更新,也没有对其他表的 fk。该插入是一个简单的插入,它没有或很少有回滚的机会。

于 2013-06-13T06:43:12.250 回答
-7

我现在总是使用 READ UNCOMMITTED。它的速度很快,问题最少。使用其他隔离时,您几乎总是会遇到一些阻塞问题。

只要您使用自动增量字段并多注意插入,然后就可以了,您就可以告别阻塞问题。

您可以使用 READ UNCOMMITED 出错,但老实说,很容易确保您的插入是完整的证明。使用来自选择的结果的插入/更新只是您需要注意的事情。(在此处使用 READ COMMITTED,或确保脏读不会导致问题)

所以去脏读(特别是大报告),你的软件会运行得更流畅......

于 2011-11-09T07:41:24.500 回答