Answers:
此隔离级别允许脏读取。一个事务可能会看到其他事务未提交的更改。
为了保持最高级别的隔离,DBMS通常会获取数据锁,这可能会导致并发损失和较高的锁开销。此隔离级别放宽了此属性。
您可能想查看Wikipedia文章上READ UNCOMMITTED
的一些示例并进一步阅读。
您可能也有兴趣查看Jeff Atwood的博客文章,内容涉及他和他的团队如何在Stack Overflow的早期解决僵局问题。据杰夫说:
但是
nolock
危险吗?您能否最终以read uncommitted
on 读取无效数据?是的,理论上。您会发现不乏数据库架构宇航员,他们开始对您使用ACID科学,而当您告诉他们您想尝试时,所有人都会发出建筑物火灾警报nolock
。的确是这样:该理论令人恐惧。但是我的想法是:“理论上,理论与实践之间没有区别。实际上,两者之间没有区别。”我永远不建议
nolock
您对任何可能出现的数据库死锁问题使用通用的“有益于您的疾病”蛇油修复程序。您应该首先尝试诊断问题的根源。但是实际上
nolock
,在您绝对知道的简单查询中添加简单,直接的只读事务似乎永远不会导致问题…… 只要您知道自己在做什么。
READ UNCOMMITTED
您可能要考虑的级别的一种替代方法是READ COMMITTED SNAPSHOT
。再次引用Jeff:
快照依赖于全新的数据更改跟踪方法……不仅仅是轻微的逻辑更改,它还要求服务器以物理方式不同地处理数据。启用此新数据更改跟踪方法后,它将为每个数据更改创建副本或快照。通过在争用时读取这些快照而不是实时数据,读取时不再需要共享锁,并且整体数据库性能可能会提高。
READ UNCOMMITTED
还会使您读取两次行,或者错过整个行。如果在阅读时发生页面拆分,则可能会丢失全部数据块。WITH(NOLOCK)
仅在结果的准确性不重要时才应使用
优点是在某些情况下可以更快。缺点是结果可能是错误的(尚未提交但可以返回的数据),并且不能保证结果是可重复的。
如果您在乎准确性,请不要使用它。
有关MSDN的更多信息:
实现脏读或隔离级别0锁定,这意味着不会发出共享锁,也不会使用独占锁。设置此选项后,可以读取未提交的数据或脏数据。在事务结束之前,可以更改数据中的值,并且行可以在数据集中显示或消失。此选项与在事务中所有SELECT语句中的所有表上设置NOLOCK的作用相同。这是四个隔离级别中限制最小的。
select
语句不必等待获取由其他事务专门锁定的资源的共享锁。
什么时候可以使用 READ UNCOMMITTED
?
良好:大的汇总报告显示总额不断变化。
有风险:几乎所有其他东西。
好消息是,大多数只读报告都属于该“ 好”类别。
可以使用它:
这大概涵盖了商务智能部门在SSRS中所做的大部分工作。当然,前面带有$符号的任何东西都是例外。与为客户提供服务和产生资金所需的相关核心指标相比,许多人对资金的热情更高。(我责怪会计师)。
有风险时
任何下降到详细信息级别的报告。如果需要该详细信息,通常意味着每一行都将与决策相关。实际上,如果您不能在不阻止的情况下提取较小的子集,则可能是由于当前正在对其进行编辑的充分原因。
历史数据。它很少会产生实际的变化,但是尽管用户理解不断变化的数据并不是完美的,但他们对静态数据却感觉不同。脏读不会在这里造成伤害,但双读有时可能会受到伤害。既然您仍然不应该对静态数据进行阻止,为什么还要冒险呢?
几乎所有提供给具有写功能的应用程序的东西。
甚至在OK情况不佳时。
NOLOCK
在这些表上使用任何东西。read uncommitted
当用户看到一些UI网格(数据精度不是很重要)时,是否应该将其用于Web应用程序。用户只想快速浏览一下可能存在的记录,并可能进行一些分页,排序和过滤。仅当用户单击“编辑”按钮时,我才会尝试以更严格的隔离级别读取最新记录。这样的方法在性能方面岂不是更好吗?
select item from things with (UPDLOCK)
。在其中放置一个快速超时,以便它在无法快速获取锁的情况下告诉用户它正在被编辑。这将确保您不仅对用户而且对开发人员安全。这里唯一的麻烦是您必须开始考虑超时以及如何在UI中处理超时。
在源极不可能更改的情况下,请使用READ_UNCOMMITTED。
当您知道在获取操作期间源可能会更改时,请不要使用READ_UNCOMMITTED。
READ UNCOMMITTED
。
READ UNCOMMITTED
正在积极使用数据的情况下,您可以从大多数情况中受益,并且您希望减少服务器上的负载以避免可能的死锁和事务回滚,因为某些用户不小心滥用了“带有数据网格的网页中的“刷新”按钮。同时查看一堆记录的用户通常不太在乎数据是否有些过时或部分更新。仅当用户将要编辑记录时,才可能需要给他/她最准确的数据。
这会给您带来脏读,并向您显示尚未提交的事务。那是最明显的答案。我认为使用它只是为了加快阅读速度不是一个好主意。如果您使用良好的数据库设计,还有其他方法可以做到。
注意未发生的事情也很有趣。READ UNCOMMITTED不仅忽略其他表锁。它本身也不会引起任何锁定。
考虑您正在生成大型报告,或者正在使用大型(可能是复杂的)SELECT语句从数据库中迁移数据。这将导致在您的交易期间可能将共享锁升级为共享表锁。可以从表中读取其他事务,但是无法进行更新。如果由于其生产数据库可能会完全停止生产数据库,这可能是一个坏主意。
如果使用的是READ UNCOMMITTED,则不会在表上设置共享锁。您可能从某些新事务中获得结果,或者可能不取决于数据插入表的位置以及SELECT事务已读取多长时间。例如,如果发生页面拆分,您可能还会两次获得相同的数据(数据将被复制到数据文件中的另一个位置)。
因此,如果在执行SELECT时可以插入数据对您来说非常重要,则READ UNCOMMITTED可能有意义。您必须考虑到您的报告可能包含一些错误,但是如果基于数百万行的报告并且在选择结果时仅更新其中的一些错误,则可能“足够好”。您的交易也可能全部失败,因为不能保证一行的唯一性。
更好的方法可能是使用快照隔离级别,但是您的应用程序可能需要进行一些调整才能使用它。这样的一个例子是,您的应用程序是否对一行进行排他锁,以防止其他人读取它并进入UI的编辑模式。快照隔离级别的确也会带来相当大的性能损失(尤其是在磁盘上)。但是您可以通过在该问题上投入硬件来克服这一问题。:)
您也可以考虑还原数据库的备份,以用于报告数据或将数据加载到数据仓库中。
我现在总是使用READ UNCOMMITTED。问题最少,速度很快。使用其他隔离时,几乎总是会遇到一些阻塞问题。
只要您使用“自动增量”字段,然后再多注意一些插入内容,然后再按您的要求,就可以告别阻塞问题。
您可以使用READ UNCOMMITED读取错误,但老实说,确保插入的内容是完整证据非常容易。使用选择结果的插入/更新只是您需要注意的事情。(在此处使用READ COMMITTED,或确保不脏的读取不会引起问题)
因此,进行“脏读”(特别是大型报告),您的软件将运行得更加顺畅...
Committed
插入和更新。至于其他问题,他还提到了使用自动增量键提及页面拆分问题的意识。我同意他的观点,即几乎所有由人类阅读的实时报告都可以忍受最后小数位的细微差异。我同意对于要通过机器读取和转换的详细列表或数据,这是另一回事,Clive也是如此。