8

事务隔离级别备忘

 3 years ago
source link: https://lotabout.me/2020/QQA-Isolation-Level-of-Database/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Table of Contents

数据库的事务有哪些隔离级别,它们解决了哪些问题?

隔离级别解决的事务的并发问题。当两个事务同时发生时,数据库最终的执行结果可以等价将事务里的各个操作排序后执行1,不过不是任意排序都可以,有些排序的结果不符合业务的预期。本节会列举其中的一些“错误”,而“隔离级别”就是一种约定,告诉我们数据库不会出现哪些“错误”。

记号:w1[x] 代表事务 1 写入行 x,r1[x] 代表事务 1 读取行 x, c1 代表提交事务 1, a1 代表回滚事务 1.

P0: Dirty Write

问题时序P0:w1[x]...w2[x]...(c1 or a1)

两个事务分别写入,然后两个事务分别提交或回滚,则事务的结果无法确定。考虑下图:

P0-dirty-write.svg

图中假设在一个事务里,满足约束 x == y,如果不做隔离,则事务结束后,数据库中的值不满足约束。

当前支持事务的数据库都可以避免上述时序。例如在 MySQL 中,如果两个事务写入同一行,后写入的事务会等待直到前一个事务结束或超时。

P1: Dirty Read

问题时序P1:w1[x]...r2[x]...(c1 or a1)

即 r2 能读取未提交的事务的修改 w1。这会导致 t2 事务过程中的约束被打破,如下图:

P1-dirty-read.svg

该时序下,在 t2 事务内部,原本的约束 x+y==100 由于 t1 的写入被打破了。

隔离级别 READ COMMITTED 的目的就是阻止该时序的发生。即在 t1 未提交时,它的修改对 t2 不可见。

P2: Fuzzy Read | Non-repeatable Read

  • 典型时序A2:r1[x]...w2[x]...c2...r1[x]...c1
  • 问题时序P2:r1[x]...w2[x]...(c1 or a1) 是 A2 的扩展

在事务 t1 读取数据后,另一个事务 t2 提交的修改对 t1 后续的读可见,则会造成不一致,如下图(A2):

A2-fuzzy-read.svg

而 P2 是对 A2 的扩展,下例虽然不违反 A2,实际使用时也有问题:

P2-fuzzy-read.svg

事务 t2 提交后的修改对 t1 可见,导致 t1 内部的约束失效。

一般数据库的隔离级别 REPEATABLE READ 能阻止 A2 的发生,但不一定能完全支持 P2。

P3: Phantom

  • 典型时序A3:r1[P]...w2[y in P]...c2...r1[P]...c1
  • 问题时序P3:r1[P]...w2[y in P]...(c1 or a1)

与 Fuzzy Read 不同,Phantom(幻读)涉及的不是单个数据行,而是查询(如 SELECT ... WHERE P)。

A3-phantom.svg

而 P3 是对 A3 的扩展,下例(H3)虽然不违反 A3,实际使用时也有问题:

P3-phantom.svg

Phantom 问题在于,查询条件隐含要求了范围数据的可重复读。需要 SERIALIZABLE 隔离级别才能防止。

P4: Lost Update

问题时序:r1[x]...w2[x]...w1[x]...c1

该时序下,事务 t1 的修改 w1 将被 t2 的修改覆盖而丢失,如下图:

P4-Lost-Update.svg

注意的是,禁用 P1 依旧会出现 P4,而禁用 P2 后就不会出现 P4,可以说 P4 是 P2 的一个子模式。

在 MySQL 中,需要使用 SELECT ... FOR UPDATE 来锁住对应的行,阻止其它事务对选中行的读写,来防止 P4 的发生。

A5: Data Item Constraint Violation

我们隐式地对数据的两行数据有约束,下面是两种破坏约束的情形:

A5A: Read Skew

问题时序:r1[x]...w2[x]...w2[y]...c2...r1[y]...(c1 or a1),示例:

A5A-Read-Skew.svg

A5B: Write Skew

问题时序:r1[x]...r2[y]...w1[y]...w2[x]...(c1 and c2 occur),示例:

A5B-Write-Skew.svg

A5A 和 A5B 在 P2(Fuzzy Read) 的加强版被禁止的情况下是不会出现的,不过仅在 ANSI 版本(A2) 被禁止的情况下依然可能出现。

从原论文摘抄如下(省略了 P4C):

(注意的是,下图假设 REPEATABLE READ 是支持了 P2 扩展的,而许多数据库的实现并不支持)

Isolation.svg

有时候更重要的不是解决问题的方法,而是认识到问题是什么。

文章里介绍了并发事务可能出现的多种问题。

  • 主要注意 P1: Dirty ReadP2: Fuzzy ReadP3: Phantom
  • P4: Lost UpdateA5: Constraint Violation 都是 P2 的变种。
  • 不过真正的实现上,P2 并没有被良好的支持,所以了解 P4、A5A、A5B 都是挺重要的

文章本来是阅读《Design Data-Intensive Applications》后想做个备忘,在给各个问题举例时发现了论文《A Critique of ANSI SQL Isolation Levels》,结果花了很长时间来理解论文里的各种情形。本文也算是另一种形式的备忘吧,只不过更“学术”了,不“实用”了。


  1. 1.并发的一致性可以参考另一篇文章 什么是顺序一致性

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK