削弱数据库中事务隔离级别可能会导致什么

大家好。联系弗拉迪斯拉夫·罗丹(Vladislav Rodin)。目前,我是OTUS高负载架构师课程的负责人,并且还教授软件架构课程。

如您所见,除了教学之外,我还一直在为博客版权材料OTUSHabré撰写文章,而今天的文章我想与《 PostgreSQL》课程的开始相吻合,该课程现已开放。




介绍


上次你和我谈过的数据库用于两个目的在于交易:以确保在竞争环境中的容错和数据访问。要完成这些任务,事务必须具有ACID属性。今天,我们将详细讨论此缩写中的字母I(隔离)


绝缘


隔离解决了在竞争环境中访问数据的问题,有效地提供了针对竞争条件的保护。理想情况下,隔离意味着序列化,即一种确保并行执行事务的结果与顺序执行结果相同的属性。此属性的主要问题是,从技术上讲,它很难提供,因此对系统性能有重大影响。这就是为什么通常会降低隔离度,接受某些异常的风险的原因,下面将对此进行讨论。某些异常发生的可能性恰好是事务隔离级别的特征。

最著名的异常是:脏读,不可重复读,幻像读,但实际上还有5种:脏写,光标丢失更新,丢失更新,读取歪斜,写入歪斜。

脏写


异常的本质是事务可以覆盖未提交的数据。

图片

这种异常是危险的,不仅因为提交两个事务后数据可能会冲突(如图所示),而且还因为违反了原子性:因为我们允许覆盖未锁定的数据,所以不清楚如何回滚一个事务而不击中另一个事务。

异常的处理非常简单:我们在记录开始之前挂断写锁,禁止其他事务更改记录,直到释放锁为止。

脏读


脏读意味着读取未提交的数据。

图片

当基于样本需要执行某些动作或做出决策时,就会出现问题。

要解决此异常,可以挂起一个读锁,但这会严重影响性能。简单地说,对于回滚事务,必须将数据的初始状态(记录之前)存储在系统中。为什么不从那里读?这是相当便宜的,因此大多数数据库默认都会删除脏读。

更新丢失


更新丢失意味着更新丢失,并且转换准确地反映了问题的实质:

图片

实际上,事务T2的结果被取消了。这种情况是通过显式或隐式写锁解决的。也就是说,我们要么简单地更新记录,然后发生隐式锁定,要么执行select for update,导致发生读写锁定。请注意,这样的操作非常危险:通过我们的“无辜”阅读,我们将阻止其他阅读。某些数据库为共享提供了更安全的选择,允许您读取数据,但不允许更改。

游标丢失更新


为了更好地控制,基座可以提供其他工具,例如光标。游标是一种结构,其中包含一组线,并允许您对其进行迭代。为select_statement声明cursor_name游标的内容由select描述。

为什么需要光标?事实是某些数据库提供了对由select选择的所有记录的锁定(读取稳定性),或仅锁定了光标当前所在的记录(光标稳定性)。借助游标稳定性,实现了短锁,如果迭代大数据样本,则可以减少锁的数量。因此,丢失的更新异常将针对光标单独突出显示。

不可重复读


不可重复读取是在执行事务期间,对同一记录的两次连续读取将导致不同的结果,因为另一笔事务介于这两次读取之间,从而更改了数据并已提交。

图片

为什么这是一个问题呢?想象一下,图中交易T2的目的是选择价格低于150立方米的所有产品 有人将价格更新为200美元 因此,安装的过滤器不起作用。

当添加两相锁或使用MVCC机制时,这些异常现象将不再发生,我想分别讨论一下。

幻影阅读


Phantom正在读取由另一个事务添加的数据。

图片

例如,当发生这种异常时,您可能会观察到最便宜产品的错误选择。

摆脱幻象阅读已经非常困难。普通的阻止是不够的,因为我们将无法阻止尚不可用的内容。2PL系统使用预测锁定,而MVCC系统使用事务调度程序来取消可能被插入中断的事务。第一和第二机制都非常沉重。

读取歪斜


当我们使用多个表时,会出现读取偏斜,其内容应以一致的方式更改。

假设有代表帖子及其元信息的

图片

一个事务从表中读取,另一个事务对其进行更改:

图片

作为事务T1的结果,该帖子的标题=好,而update_by = T2,这有些不一致。

实际上,这是不可重复的读取,但是作为多个表的一部分。

为了更正,T1可以在将要读取的所有行上挂锁,以防止T2更改信息。对于MVCC,交易T2将被取消。如果使用游标,那么针对这种异常情况的保护就变得很重要。

写偏斜


使用一个例子也可以更容易地解释这种异常:假设在我们的系统中至少有一名医生必须值班,但是两位医生都决定取消其职责:

图片

图片

异常导致了一个事实,即没有医生值班。为什么会这样呢?因为该事务检查了另一个事务可能违反的条件,并且由于隔离,所以我们没有看到此更改。

这是相同的不可重复读取。或者,选择可以在这些记录上挂锁。

写入偏斜和读取偏斜是先前异常的组合。您可以考虑写偏斜,它本质上是幻像读取。考虑一个表,其中有雇员的姓名,工资和他们从事的项目:

图片

图片

结果,我们得到如下图:每个经理都认为他的变更不会导致预算,因此他们进行了人事变更,从而导致超支。

问题的原因与幻像读取完全相同。

发现


削弱数据库中事务隔离的级别是安全性和性能之间的折衷,应该根据发生任何异常情况时对业务的潜在风险来选择该级别。



了解有关该课程的更多信息。



All Articles