笔记"/>
A Critique of ANSI SQL Isolation Levels阅读笔记
很久没正儿八经的读过论文了,最近因为工作的原因需要阅读一篇数据库相关的论文,叫A Critique of ANSI SQL Isolation Levels。最近加班太多,时间有限,先大概总结一下。
由于本人对数据库原理知之甚少,本文只是记录了对这篇论文字面意思的理解,其中必定存在大量误解,请大家交流指正。
本篇共分为5个小节,下面就通过分节梳理的方式来记录阅读笔记。
0、摘要讲了什么?
ANSI SQL-92基于三种异象(phenomena)定义了隔离级别。该论文表明ANSI定义的这些异象不能描述一些常见的隔离级别,包括标准的锁实现的隔离级别。该论文通过分析这些异象所存在的问题,提出了一个新的异象,可以用来更好的描述隔离级别,并定义了一个重要的多版本隔离类型——快照隔离。
读完摘要,有以下几点疑惑:
- 作者提出了什么样的异象?
- 为什么要提出这个异象?
- 为什么这个异象可以更好的描述隔离级别?
- 快照隔离是什么?它和其他几种隔离级别有什么关系?为什么需要它?
1、第一节讲了什么?
首先介绍了事务隔离的作用,以及事务隔离级别对并发事务的影响,然后介绍了ANSI定义的四种隔离级别:读未提交、读已提交、可重复读、串行化。还有三种异象:脏读、非重复读、幻读。作者指出使用异象定义隔离级别有很多缺点,而且这些异象的定义也是含糊不清的。最后,介绍了本文的结构及各小节所涉及的内容。
2、第二节讲了什么?
讲了隔离级别相关的术语,定义了ANSI SQL隔离级别 和 锁隔离级别。
2.1 三种异象
P1(脏读):事务1修改了某个数据项,事务2在事务1执行提交或回滚之前,读取了该数据项。
P2(不可重复读):事务1读取了某个数据项,然后事务2修改了该数据项并进行了提交,接着事务1又读取了该数据项,此时事务1发现该数据项被修改或删除了。
P3(幻读):事务1读取了一个满足特定条件的数据集合,然后事务2创建了一个新的数据项,且该数据项满足前面事务1读取数据集合的条件,并且提交了,接着事务1在重复读取上述特定条件的数据集合时发现新增了数据项。
2.2 三种异象的形式化定义
异象 | 宽泛定义 & 严格定义 |
异象P1(脏读) | 宽泛定义P1:w1[x] … r2[x] … ((c1 or a1) and (c2 or a2) in any order)
严格定义A1:w1[x] … r2[x] … (a1 and c2 in any order) |
异象P2 (不可重复读) | 宽泛定义P2: r1[x] … w2[x] … ((c1 or a1) and (c2 or a2) in any order)
严格定义A2: r1[x] … w2[x] … c2 … r1[x] … c1 |
异象P3(幻读) | 宽泛定义P3: r1[P] … w2[y in P] … ((c1 or a1) and (c2 or a2) any order)
严格定义A3: r1[P] … w2[y in P] … c2 … r1[P] … c1 |
2.3 ANSI定义的四种隔离级别
ANSI通过下面的表格定义了四种隔离级别
隔离级别 | P1(或者A1) 脏读 | P2(或者A2) 不可重复读 | P3(或者A3) 幻读 |
读未提交 | 允许 | 允许 | 允许 |
读已提交 | 禁止 | 允许 | 允许 |
可重复读 | 禁止 | 禁止 | 允许 |
串行化 | 禁止 | 禁止 | 禁止 |
隔离级别通过异象定义,不同的隔离级别,所禁止的异象不一样。比如 读已提交 隔离级别 是禁止异象P1的出现。
2.4 基于锁定义的隔离级别
一致性等级(锁隔离级别) | 在数据项上使用读锁 | 在数据项上使用写锁 |
级别0 | 不需要 | 合法写 |
级别1(锁-读未提交) | 不需要 | 合法写 写长锁 |
级别2(锁-读已提交) | 合法读 读短锁 | 合法写 写长锁 |
游标稳定性 | 合法读 当前游标持有读锁 谓词读短锁 | 合法写 写长锁 |
锁-可重复读 | 合法读 读长锁 谓词读短锁 | 合法写 写长锁 |
级别3(锁-串行化) | 合法读 读长锁 | 合法写 写长锁 |
3、第三节讲了什么?
3.1 P0(脏写)异象
首先引入一个新的异象P0(脏写),它的定义是:
P0: w1[x] ... w2[x] ... ((c1 or a1) and (c2 or a2) in any order)
脏写会导致更新丢失。在这种情况下,不管是T1还是T2回滚都会有问题,假设x初始值是0,T1写入了x=1,T2写入了x=2,此时若T1回滚,则将会擦掉T2写入的值,若T2回滚,则T1的写入也会被擦掉。
3.2 ANSI异象定义分析(宽泛还是严格)?
在本博客2.2中,分别给出了ANSI所定义的三种异象的宽泛形式和严格形式。该论文指出,ANSI所定义的三种异象都应该是宽泛形式。原因如下所示:
1)假设事务1从x账户给y账户转40元,且有如下操作历史:
H1: r1[x=50] w1[x=10] r2[x=10] r2[y=50] c2 r1[y=50] w1[y=90] c1
该操作历史没有出现A1、A2、A3异象,但对事务2来说,它所读到的数据,违背了x+y=100的一致性。不过,此时可以看出H1出现了P1异象,即脏读的宽泛定义。
2)假设事务2从x账户给y账户转40元,且有如下操作历史:
H2: r1[x=50] r2[x=50] w2[x=10] r2[y=50] w2[90] c2 r1[y=90] c1
该操作历史没有出现A1、A2、A3异象,但对事务1来说,它所读到的数据,违背了x+y=100的一致性。不过,此时可以看出H2出现了P2异象,即不可重复读的宽泛定义。
3)假设事务1查找在职员工列表,事务2新增一个在职员工的记录,并更新员工数量,且有如下历史:
H3: r1[P] w2[insert y to P] r2[z] w2[z] c2 r1[z] c1
该操作历史没有出现A1、A2、A3异象,但对事务1来说,前面读取的在职员工列表的大小,和后面读取的在职员工数量不一致。不过,此时可以看出H3出现了P3异象,即幻读的宽泛定义。
3.3 基于上述异象得到ANSI定义的隔离级别
隔离级别 | P0(脏写) | P1(脏读) | P2(不可重复读) | P3(幻读) |
读未提交 | 禁止 | 允许 | 允许 | 允许 |
读已提交 | 禁止 | 禁止 | 允许 | 允许 |
可重复读 | 禁止 | 禁止 | 禁止 | 允许 |
串行化 | 禁止 | 禁止 | 禁止 | 禁止 |
4、第四节讲了什么?
本节介绍了一些可商用的隔离级别实现。
4.1 P4(更新丢失)异象
形式化定义:
P4:r1[x] ... w2[x] ... w1[x] ... c1
假设有如下操作历史:
H4: r1[x=100] r2[x=100] w2[x=120] c2 w1[x=130] c1
4.2 游标稳定性隔离级别
P4C异象:rc1[x] ... w2[x] ... w1[x] ... c1
其中,rc1表示事务1读取游标。
分析可知,游标稳定性隔离级别位于读已提交和可重复读之间。
4.3 快照隔离
快照隔离是多版本并发控制的一种实现方法。
隔离等级比较:读未提交 < 读已提交 < (可重复读 >< 快照) < 串行化。
先留下几个问题,后面再梳理
1)可重复读隔离和快照隔离的区别是什么?
2)可重复读隔离和快照隔离之间的优先级为什么不能比较?
3)可重复读隔离和快照隔离之间有哪些互相没有的特性?
5、第五节讲了什么?
根据是否允许出现各种异象来定义隔离级别,原文总结如下:
隔离级别 | P0(脏写) | P1(脏读) | P4C(游标丢失更新) | P4(丢失更新) | P2(不可重复读) | P3(幻读) | A5A(读偏) | A5B (写偏) |
读未提交 | 禁止 | 允许 | 允许 | 允许 | 允许 | 允许 | 允许 | 允许 |
读已提交 | 禁止 | 禁止 | 允许 | 允许 | 允许 | 允许 | 允许 | 允许 |
游标稳定性 | 禁止 | 禁止 | 禁止 | 有时允许 | 有时允许 | 允许 | 允许 | 有时允许 |
可重复读 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 允许 | 禁止 | 禁止 |
快照 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 有时允许 | 禁止 | 允许 |
串行化 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 |
更多推荐
A Critique of ANSI SQL Isolation Levels阅读笔记
发布评论