削弱数据库中的事务隔离级别会导致什么结果?

大家好。 弗拉迪斯拉夫·罗丹正在联系。 我目前是 OTUS 高工作负载架构师课程的课程负责人,同时也教授软件架构课程。

除了教学之外,您可能已经注意到,我正在为 Habré 的 OTUS 博客撰写原创材料,我想与今天的文章相一致,以配合课程的推出 “PostgreSQL”,现已开放报名。

削弱数据库中的事务隔离级别会导致什么结果?

介绍

В 上一次 我们讨论了数据库中的事务可以解决两个问题:确保容错和在竞争环境中访问数据。 要完全执行这些任务,事务必须具有 ACID 属性。 今天我们就来详细聊聊这封信 我(隔离) 在这个缩写中。

绝缘

隔离解决了在竞争环境中访问数据的问题,本质上提供了针对竞争条件的保护。 理想情况下,隔离意味着序列化,这是一种确保并行执行事务的结果与顺序执行事务相同的属性。 该属性的主要问题是技术上提供起来非常困难,因此对系统性能有很大影响。 这就是为什么隔离常常被削弱,接受某些异常的风险,这将在下面讨论。 发生某些异常的可能性精确地表征了事务隔离的级别。

最广为人知的异常是:脏读、不可重复读、幻读,但实际上还有5种:脏写、游标丢失更新、丢失更新、读倾斜、写倾斜。

脏写

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

削弱数据库中的事务隔离级别会导致什么结果?

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

这种异常可以很简单地处理:我们在开始记录之前给记录附加一个锁,禁止其他事务更改记录,直到锁被移除。

脏读

脏读是指读取未提交的数据。

削弱数据库中的事务隔离级别会导致什么结果?

当需要根据样本采取行动或做出决策时,就会出现问题。

为了纠正异常,您可以附加读锁,但这会极大地影响性能。 说得更简单,对于回滚事务,数据的初始状态(开始记录之前)必须保存在系统中。 为什么不从那里读呢? 它足够便宜,大多数数据库默认都会删除脏读。

丢失更新

Lost update 就是丢失更新的意思,翻译相当准确地反映了问题的本质:

削弱数据库中的事务隔离级别会导致什么结果?

事实上,交易T2的结果是相反的。 这种情况可以通过显式或隐式写锁来纠正。 也就是说,我们要么简单地更新记录,然后发生隐式锁,要么执行 选择更新,导致发生读写锁。 请注意,这样的操作是相当危险的:通过我们的“无辜”阅读,我们阻止了其他阅读。 一些数据库提供更安全的 选择分享,允许读取数据但不能修改数据。

光标丢失更新

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

为什么需要光标? 事实上,某些数据库对 select 选择的所有记录提供锁定(读稳定性),或者仅对游标当前所在的记录提供锁定(游标稳定性)。 通过游标稳定性,实现了短锁,这使得我们在迭代大量数据样本时可以减少锁的数量。 因此,针对游标单独隔离丢失更新异常。

不可重复读取

不可重复读是指在我们的事务执行过程中,连续2次读取同一条记录会导致不同的结果,因为另一个事务介入了这两次读取之间,改变了我们的数据并被提交。

削弱数据库中的事务隔离级别会导致什么结果?

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

当添加两相互锁或使用MVCC机制时,这些异常现象就不再发生,我想单独讨论。

幻读

幻影是对另一个事务添加的数据的读取。

削弱数据库中的事务隔离级别会导致什么结果?

举个例子,我们可以观察到当这种异常发生时,我们会错误地选择最便宜的产品。

摆脱幻读已经相当困难了。 定期阻止是不够的,因为我们无法阻止尚不存在的东西。 2PL 系统使用预测锁定,而 MVCC 系统具有事务调度程序,可以回滚可能因插入而中断的事务。 第一和第二机构都相当重。

读取倾斜

当我们使用多个表时,会发生读取偏差,这些表的内容必须一致地更改。

假设我们有代表帖子及其元信息的表格:

削弱数据库中的事务隔离级别会导致什么结果?

一个事务从表中读取,另一个事务修改它们:

削弱数据库中的事务隔离级别会导致什么结果?

作为事务 T1 的结果,该帖子的 title = Good,并且 Updated_by = T2,这是某种不一致。

事实上,这是一个不可重复的读取,而是作为几个表的一部分。

为了解决这个问题,T1 可以在它将读取的所有行上加锁,这将防止事务 T2 更改信息。 如果是MVCC,T2交易将被取消。 如果我们使用游标,防止这种异常现象就变得很重要。

写入倾斜

这种异常现象也更容易用一个例子来解释:假设在我们的系统中至少有一名医生应该值班,但两名医生都决定取消他们的值班:

削弱数据库中的事务隔离级别会导致什么结果?

削弱数据库中的事务隔离级别会导致什么结果?

这种异常现象意味着没有医生会值班。 为什么会发生这种情况? 因为该事务正在检查可能被另一个事务违反的条件,并且由于隔离,我们没有看到此更改。

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

写倾斜和读倾斜是前面异常的组合。 您可以考虑写入倾斜,这本质上是幻读。 考虑一个包含员工姓名、工资以及他们从事的项目的表:

削弱数据库中的事务隔离级别会导致什么结果?

削弱数据库中的事务隔离级别会导致什么结果?

结果,我们得到了下面的画面:每个经理都认为他们的变革不会导致超出预算,因此他们进行了人事变动,这些变动共同导致了成本超支。

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

发现

放宽数据库中的事务隔离级别是安全性和性能之间的权衡;应根据发生某些异常时对业务的潜在风险来选择该级别。

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

来源: habr.com

添加评论