高级数据库系统 06:隔离性

墨尔本大学 COMP90050 课程笔记

Posted by YEY on July 15, 2020

Lecture 06 隔离性

参考教材Transaction Processing: Concepts and Techniques, Jim Gray and Andreas Reuter, Morgan Kaufmann, 1993

在上节课中,我们讨论了涉及多个并行运行事务的并发问题,以及它产生的原因和解决方案。这节课,我们将学习一个与之相关的概念:隔离性 (Isolation)

1. 隔离性概念

1.1 为什么需要隔离性

如果有多个彼此存在依赖关系的事务在运行,例如:两个事务都需要对某个共享变量进行更改,我们介绍了锁机制以及如何利用锁处理该问题。这节课我们将学习更加通用的案例和解决方案。

我们在之前已经介绍过隔离性的概念,对于多个并行运行的事务,如何保证它们看起来好像是系统中唯一运行着的事务,或者保证它们能够并发运行。如果我们可以保证一个事务完成的更改对另一个并行运行的事务不会造成任何运行,我们就可以维持隔离性。

只要每个事务本身都是一致的,那么隔离性就可以保证一致性

一致性类型可以表示为不变式,例如:

  • 银行账户余额必须为正,账户余额的变化也应记录在分类账簿关系中。
  • 如果在 EMPLOYEE 关系中插入了一条记录,则在 ADDRESS 关系中必须存在对应的记录 (参照完整性)
  • 反应堆棒的移动速度不能超过 X 厘米/秒

我们需要隔离性来确保数据库的一致性。数据库或者事务的一致性可以通过一些规则给出 (例如,在一个银行系统中,账户余额必须是正数)。

例子

  • 账户 A 目前余额为 550 元,有两个事务 T1 和 T2,其中,T1 从账户 A 转出 100 元,T2 从账户 A 转出 500 元。

  • 对于 T1,它先读取账户 A 的余额 550 元,然后在此基础上减去 100 元;对于 T2,它先读取账户 A 的余额 550 元,然后在此基础上减去 500 元。

  • 在不采取任何隔离性控制的情况下,如果单独看 T1 和 T2,它们都是合法事务;但是,如果两者放在一起,将导致账户余额最终变为负数,这将无法维持该数据库的一致性。

1.2 如何实现隔离性

我们可以通过顺序处理每个事务来实现隔离性,但这通常效率不高并且将导致很差的响应时间。

在并发执行事务时,我们需要实现以下目标:

  • 并发执行不应引起应用程序 (事务) 故障。
  • 并发执行的吞吐量或响应时间不应比串行执行差。

为了实现隔离,我们需要锁和/或限制对象上的并发操作类型。我们已经在前一节课中介绍过锁机制,这里,基本思想是由锁完成一些控制,以决定哪些事务可以修改某个对象。这里,任何数据都可以视为对象:它可以是数据库中的任意一条数据或者磁盘中的一个块,或者一个数据块序列等等。

  • 例如:允许并发读取同一对象,但禁止并发对同一对象进行 “写-写” 或者 “读-写” 操作。

1.3 依赖模型

可以通过一种名为 依赖模型 (dependency model) 的方法研究隔离性。

一个事务 $T_i$ 具有输入集 $I_i$ (被读取的对象) 和输出集 $O_i$ (被修改的对象)。

对于所有的并发事务,为了维持一致性,必须满足:

\[O_i\cap (I_j \cup O_j)=\emptyset \quad \forall \,i\neq j\]

注意,$O_j$ 和 $I_j$ 不一定是不相交的,即允许 $O_j\cap I_j \neq \emptyset$。

例如:

由于在许多情况下,由于输入和输出可能取决于状态/无法提前预知,因此这种方法无法提前规划。

每当修改 (写操作) 一个对象 $o$ 时,其版本号 $i$ 就会递增,并且记为 <$o, i$>。如果某个对象被事务 T1 修改 (WRITE) 并且被另一个事务 T2 读取 (READ),那么它将创建以下依赖关系:

WRITE --> READ dependency between T1 and T2.
Other possible dependencies are:
WRITE --> WRITE,
READ --> WRITE,
READ --> READ.

最后一个依赖形式不会导致不一致性,因此我们将忽略它。(因为读对象同一个版本的多个事务不会产生对另一个版本的依赖,只有写操作会产生版本和依赖。)

下图给出了前三种依赖形式:

  • READ-WRITE 依赖

    如果 T1 读取了对象 $o$, 然后 T2 对 $o$ 进行了写操作,那么,T1 的 READ 操作将失效,其读取的对象 $o$ 的值不再有效,因为 T2 已经对其进行了重写。

  • WRITE-READ 依赖

    当对象 $o$ 被 T1 执行写操作并返回,然后被 T2 读取。

  • WRITE-WRITE 依赖

    当多个事务对同一对象执行写操作时,对象的最终值取决于最后一个写操作,之前的其他写操作将会丢失。

1.4 三种有害依赖

1.5 锁的模式

当一个对象被某个事务以 不兼容模式 (incompatible mode) 锁定时,不应将该对象上的锁授予另一个事务。在这种情况下,请求事务被迫等待直到锁变得兼容为止。

锁兼容性矩阵:

1.6

下节内容:隔离性

知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 欢迎转载,并请注明来自:YEY 的博客 同时保持文章内容的完整和以上声明信息!