【发布时间】:2010-03-18 15:30:06
【问题描述】:
通俗的说,使用的优缺点是什么
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在查询 .NET 应用程序和报告服务应用程序?
【问题讨论】:
标签: sql-server tsql isolation-level
通俗的说,使用的优缺点是什么
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
在查询 .NET 应用程序和报告服务应用程序?
【问题讨论】:
标签: sql-server tsql isolation-level
此隔离级别允许脏读。一个事务可能会看到其他事务所做的未提交更改。
为了保持最高级别的隔离,DBMS 通常会在数据上获取锁,这可能会导致并发丢失和高锁定开销。这个隔离级别放宽了这个属性。
您可能需要查看Wikipedia article on READ UNCOMMITTED 以获取一些示例和进一步阅读。
您可能也有兴趣查看 Jeff Atwood 的 blog article,了解他和他的团队如何在 Stack Overflow 早期解决死锁问题。根据杰夫的说法:
但是
nolock危险吗?你能结束吗? 使用read uncommitted读取无效数据?是的,理论上。你会 发现不缺数据库 开始的建筑宇航员 将酸科学放在你和所有人身上 但拉建筑物火警时 你告诉他们你想试试nolock。 这是真的:这个理论很可怕。但 这就是我的想法:“理论上有 理论和理论没有区别 实践。在实践中是有的。”我永远不会推荐使用
nolock作为一般的“对你有什么好处” 任何数据库的蛇油修复 您可能遇到的死锁问题。你 应尝试诊断源头 先说问题。但实际上,将
nolock添加到您绝对知道是简单、直接的只读事务的查询中似乎永远不会导致问题... 只要您知道自己在做什么。 >
您可能要考虑的READ UNCOMMITTED 级别的替代方案是READ COMMITTED SNAPSHOT。再次引用 Jeff:
快照依赖于一种全新的数据更改跟踪方法……不仅仅是轻微的逻辑更改,它还需要服务器以不同的物理方式处理数据。一旦启用了这种新的数据更改跟踪方法,它就会创建每个数据更改的副本或快照。 通过在争用时读取这些快照而不是实时数据,读取时不再需要共享锁,并且整体数据库性能可能会提高。
【讨论】:
READ UNCOMMITTED can also cause you to read rows twice, or miss entire rows。如果您在阅读时发生页面拆分,那么您可能会丢失整个数据块。 WITH(NOLOCK) 仅应在结果的准确性不重要时使用
read uncommited 我最喜欢的用例是调试事务中发生的事情。
在调试器下启动您的软件,当您单步执行代码行时,它会打开一个事务并修改您的数据库。当代码停止时,您可以打开查询分析器,设置读取未提交的隔离级别并进行查询以查看发生了什么。
您还可以使用它来查看长时间运行的过程是否卡住或使用带有count(*) 的查询正确更新您的数据库。
如果您的公司喜欢制作过于复杂的存储过程,那就太好了。
【讨论】:
这对于查看长插入查询的进度、进行粗略估计(如COUNT(*) 或粗略的SUM(*))等很有用。
换句话说,脏读查询返回的结果很好,只要您将它们视为估计值并且不根据它们做出任何关键决策。
【讨论】:
优点是在某些情况下它可以更快。缺点是结果可能是错误的(尚未提交的数据可能会被返回)并且不能保证结果是可重复的。
如果您关心准确性,请不要使用它。
更多信息在MSDN:
实现脏读或隔离级别 0 锁定,这意味着不会发出共享锁,也不会使用排他锁。设置此选项时,可以读取未提交或脏数据;数据中的值可以更改,并且行可以在事务结束之前在数据集中出现或消失。此选项与在事务中的所有 SELECT 语句中的所有表上设置 NOLOCK 具有相同的效果。这是四个隔离级别中限制最少的。
【讨论】:
select 语句不必等待获取被其他事务独占锁定的资源的共享锁。
什么时候可以使用READ UNCOMMITTED?
良好:大汇总报告显示不断变化的总数。
有风险:几乎所有其他事情。
好消息是大多数只读报告都属于良好类别。
可以使用:
这可能涵盖了商业智能部门将在 SSRS 等中所做的大部分工作。当然,前面有 $ 符号的东西除外。许多人对金钱的计算比应用于服务客户和产生金钱所需的相关核心指标要热情得多。 (我责怪会计师)。
有风险时
任何详细级别的报告。如果需要该详细信息,则通常意味着每一行都与决策相关。事实上,如果您无法在不阻塞的情况下提取一个小子集,则可能是因为它当前正在被编辑。
历史数据。它很少产生实际的差异,但尽管用户明白不断变化的数据不可能完美,但他们对静态数据的感觉却不尽相同。脏读在这里不会受到伤害,但偶尔会出现双重阅读。既然您不应该对静态数据设置块,为什么要冒险呢?
几乎所有支持应用程序的东西都具有写入功能。
即使是好的场景也不行。
NOLOCK 来做任何事情。【讨论】:
read uncommitted 用于 Web 应用程序。用户只想快速了解可能存在哪些记录,并且可能需要一些分页、排序和过滤。只有当用户单击编辑按钮时,我才会尝试读取具有更严格隔离级别的最新记录。这种方法在性能方面不应该更好吗?
select item from things with (UPDLOCK) 。在那里设置一个快速超时,这样如果它不能快速获取锁,它就会告诉用户它正在被编辑。这不仅可以保护您免受用户的侵害,还可以保护开发人员。这里唯一的麻烦是您必须开始考虑超时以及如何在 UI 中处理它。
关于报告,我们在所有报告查询中使用它,以防止查询陷入数据库。我们可以这样做,因为我们提取的是历史数据,而不是微秒级数据。
【讨论】:
在源极不可能更改的情况下使用 READ_UNCOMMITTED。
如果您知道在 fetch 操作期间源可能会发生变化,请不要使用 READ_UNCOMMITTED。
【讨论】:
READ UNCOMMITTED 也是如此。
READ UNCOMMITTED 中受益,当您的数据被积极使用并且您希望减少服务器上的负载以避免可能的死锁时和事务回滚只是因为一些用户不小心滥用了带有数据网格的网页中的“刷新”按钮。同时查看一堆记录的用户,通常不会太在意数据是否有点过时或部分更新。只有当用户即将编辑记录时,您才可能希望为他/她提供最准确的数据。
这将为您提供脏读,并向您显示尚未提交的事务。这是最明显的答案。我认为仅仅为了加快阅读速度而使用它并不是一个好主意。如果您使用良好的数据库设计,还有其他方法可以做到这一点。
注意没有发生的事情也很有趣。 READ UNCOMMITTED 不仅忽略其他表锁。它本身也不会导致任何锁定。
假设您正在生成一个大型报告,或者您正在使用大型且可能很复杂的 SELECT 语句将数据迁移出数据库。这将导致在事务期间可能升级为共享表锁的共享锁。其他事务可以从表中读取,但无法更新。如果它是一个生产数据库,这可能不是一个好主意,因为生产可能会完全停止。
如果您使用 READ UNCOMMITTED,您将不会在表上设置共享锁。您可能会从一些新事务中获得结果,或者您可能不依赖于数据插入表的位置以及您的 SELECT 事务读取了多长时间。例如,如果发生页面拆分(数据将被复制到数据文件中的另一个位置),您也可能会获得两次相同的数据。
因此,如果在执行 SELECT 时可以插入数据对您非常重要,那么 READ UNCOMMITTED 可能是有意义的。您必须考虑到您的报告可能包含一些错误,但如果它基于数百万行并且在选择结果时只有少数行被更新,这可能“足够好”。您的事务也可能一起失败,因为可能无法保证行的唯一性。
更好的方法可能是使用 SNAPSHOT ISOLATION LEVEL,但您的应用程序可能需要进行一些调整才能使用它。例如,如果您的应用程序对一行进行了排他锁以防止其他人读取它并进入 UI 中的编辑模式。 SNAPSHOT ISOLATION LEVEL 也会带来相当大的性能损失(尤其是在磁盘上)。但是你可以通过在问题上投入硬件来克服这个问题。 :)
您还可以考虑恢复数据库的备份以用于报告数据或将数据加载到数据仓库中。
【讨论】:
它可以用于一个简单的表,例如在一个只插入的审计表中,其中没有对现有行的更新,也没有对其他表的 fk。该插入是一个简单的插入,它没有或很少有回滚的机会。
【讨论】:
我现在总是使用 READ UNCOMMITTED。它的速度很快,问题最少。在使用其他隔离时,您几乎总会遇到一些阻塞问题。
只要您使用 Auto Increment 字段并多注意插入,然后就可以了,您就可以告别阻塞问题。
您可以使用 READ UNCOMMITED 出错,但老实说,很容易确保您的插入是完整的证明。使用来自选择的结果的插入/更新只是您需要注意的事情。 (在此处使用 READ COMMITTED,或确保脏读不会导致问题)
所以去脏读(特别是大型报告),你的软件会运行得更流畅...
【讨论】:
Committed 进行插入和更新。至于其他问题,他在提到使用自动递增键时也表现出对分页问题的认识。我同意他的观点,几乎所有只供人类阅读的现场报道都可以容忍小数点后的细微差异。我同意对于注定要被机器读取和转换的详细列表或数据是另一回事,Clive 也是如此。