摘要:

ANSI SQL-92[MS,ANSI]根据现象定义隔离级别:脏读、不可重复读和幻影。
由经典的可序列化性定义定义的,加上三个被禁止的操作子序列,称为现象。

ANSI SQL定义无法描述几个流行的隔离级别,包括这些级别的标准锁定实现。
对现象的模糊性进行调查可以得出更清晰的定义;此外,还引入了新的现象,更好地描述了隔离类型。定义了一种重要的多版本隔离类型,快照隔离。

1、简介

ANSI隔离级别与锁调度程序的行为有关,它通过三种方式定义了一致性程度:锁定、数据流图和异常。通过现象(异常)定义隔离级别旨在允许SQL标准的非基于锁的实现。

2、隔离定义

2.1概念

可串行化:

按顺序一次执行一个事务的历史具有相同的依赖关系图(事务间时态数据流),如果历史相当于一个串行历史,那么它是可串行化的。

冲突:

如果历史记录中的两个操作是由同一数据项上的不同事务执行的,并且其中至少有一个是写入操作,则称为冲突。冲突操作也可能发生在谓词锁覆盖的一组数据项上以及单个数据项上。

2.2ANSI SQL 隔离级别

ANSI SQL隔离设计人员寻求一个允许许多不同实现的定义,而不仅仅是锁定。

P0 (脏写):

事务T1修改数据项。然后,另一个事务T2在T1执行提交或回滚之前进一步修改该数据项。如果T1或T2随后执行回滚,则不清楚正确的数据值应该是什么。

P1 (脏读):

事务T1修改数据项。
然后,另一个事务T2在T1执行提交或回滚之前读取该数据项。
如果T1随后执行回滚,则T2读取的数据项从未提交过,因此也从未真正存在过。

P2 (不可重复或模糊读取):

事务T1读取一个数据项。
然后,另一个事务T2修改或删除该数据项并提交。
如果T1随后尝试重新读取该数据项,则会收到修改后的值或发现该数据项已被删除。

P3 (幻影):

事务T1读取满足某些<搜索条件>的一组数据项。
事务T2然后创建满足T1的<搜索条件>的数据项并提交。如果T1然后以相同的<搜索条件>重复其读取,它将获得一组与第一次读取不同的数据项。

表1.根据三种原始现象定义的ANSI SQL隔离级别
隔离级别 P1(脏读) P2(不可重复读) P3(幻读)
ANSI读未提交 可能 可能 可能
ANSI读已提交 不可能 可能 可能
ANSI可重复读 不可能 不可能 可能
ANOMALY 可串行化 不可能 不可能 不可能

PS:隔离级别由禁止其经历的现象定义

2.3Locking锁定

大多数SQL产品使用基于锁的隔离
如果一个事务持有一个锁,而另一个事务请求一个冲突的锁,那么在释放前一个事务的冲突锁之前,不会授予新的锁请求。

基本的序列化定理是,格式良好的两阶段锁定保证了可序列化性——在两阶段锁定下产生的每个历史都相当于一些串行历史。相反,如果一个事务不是格式良好的或分为两个阶段的,那么除了退化的情况外,不可序列化的执行历史记录是可能的

表 2. 根据锁定义的一致性程度和锁定隔离级别
一致性 level = Locking 隔离级别 读锁 数据项和谓词 (除非另有说明,否则相同) 写锁 数据项和谓词 (总是一样的)
Degree 0 不需要 Well-formed Writes
Degree 1 = Locking 读未提交 不需要 Well-formed Writes 长持续时间写锁
Degree 2 = Locking 读已提交 Well-formed Reads 短时读锁(两个) Well-formed Writes, 长持续时间写锁
游标稳定性 (see Section 4.1) Well-formed Reads 读取当前游标上保持的锁 短时读谓词锁 Well-formed Writes, 长持续时间写锁
Locking 可重复读 长持续时间数据项读取锁定 短时读谓词锁 Well-formed Writes, 长持续时间写锁
Degree 3 = Locking 串行化 Well-formed Reads 长持续时间读取锁(两个) Well-formed Writes, 长持续时间写锁

3.分析ANSI SQL隔离级别

四种现象表述式:

w1[x]—-表示事务1对数据项x的写入(即数据项的“修改”方式),
r2[x]—-表示事务2对x的读取。
事务1读取和写入满足谓词P的一组记录分别由r1[P]和w1[P]表示。
事务1的提交和中止(回滚)分别写为“c1”和“a1”。

脏写: P0: w1[x]…w2[x]…((c1 or a1) and (c2 or a2) 按任意顺序)
脏读: P1: w1[x]…r2[x]…((c1 or a1) and (c2 or a2) 按任意顺序)
模糊或不可重复读: P2: r1[x]…w2[x]…((c1 or a1) and (c2 or a2) 按任意顺序)
幻读 P3: r1[P]…w2[y in P]…((c1 or a1) and (c2 or a2) 按任意顺序)

表3.是根据以上现象拟定的ANSI隔离等级的定义

表3:根据四种现象定义的ANSI SQL隔离级别
隔离级别 P0 脏写 P1 脏读 P2 模糊读 P3 幻影
未提交读 不可能 可能 可能 可能
已提交读 不可能 不可能 可能 可能
可重复读 不可能 不可能 不可能 可能
可串行化 不可能 不可能 不可能 不可能

4.其他隔离类型

4.1游标稳定性

游标稳定性旨在防止丢失更新现象。
读已提交<游标稳定性<可重复读

P4 (丢失更新):

当事务T1读取数据项,然后T2更新数据项(可能基于先前的读取),然后T1(基于其先前的读取值)更新数据项并提交时,就会发生丢失更新异常。

游标稳定性表述式:

P4: r1[x]…w2[x]…w1[x]…c1 (丢失更新)

游标稳定性隔离级别扩展了SQL游标的读提交锁定行为,方法是为从游标获取添加新的读操作,并要求在游标的当前项上保持锁。锁定将一直保持,直到光标移动或关闭(可能是通过提交)。自然地,抓取事务可以更新行,在这种情况下,在事务提交之前,即使在光标移动到后续抓取之后,该行仍将保持写锁。

4.2 快照隔离

快照隔离是一种多版本方法,该方法允许通过只读事务读取快照。因此单值(SV)历史不能正确反映时间动作序列。
在任何时候,每个数据项都可能有多个版本,由活动和提交的事务创建。事务读取必须选择适当的版本。

快照隔离概念:

每个事务从事务启动时(提交的)数据的快照中读取数据,称为其启动时间戳(开始时间戳)。此时间可以是事务首次读取之前的任何时间。
在快照隔离中运行的事务在尝试读取时不会被阻止,只要可以维护其开始时间戳中的快照数据。事务的写入(更新、插入和删除)也将反映在此快照中,如果事务第二次访问(即读取或更新)数据将再次读取。
事务开始时间戳之后活动的其他事务的更新对事务不可见。
[

](https://blog.csdn.net/sunxue299/article/details/121367606)
当事务T1准备提交时,它会获得一个提交时间戳,该时间戳大于任何现有的开始时间戳或提交时间戳。只有在T1的执行间隔[StartTimestamp,Commit Timestamp]中没有其他具有提交时间戳的事务T2写入T1也写入的数据时,事务才会成功提交。否则,T1将中止。此功能称为Firstcommitter wins,用于防止更新丢失(现象P4)。当T1提交时,其更改对于开始时间戳大于T1提交时间戳的所有事务都可见

快照隔离是不可序列化的,因为事务的读取发生在一个瞬间,而写入发生在另一个瞬间。

其他多版本系统

其他多版本的模式,一些商业产品维护对象的版本,只是将快照隔离限制为只读事务,例如SQL-92、Rdb和其他一些数据库中的SET TRANSACTION read only[MS、HOB、ORA];Postgres和Illustra[STO、ILL]长期维护此类版本,并提供时间旅行查询)。
其他允许更新事务,但不提供第一提交者wins保护,(例如Oracle读取一致性隔离【ORA】)。

隔离类型图表

**表4:允许以可能的异常为特征的隔离类型。**
隔离级别 P0 脏写 P1 脏读 P4C Cursor Lost Update P4 Lost Update P2 模糊读 P3 幻影 A5A 读偏斜 A5B 写偏斜
未提交读 == Degree 1 不可能 可能 可能 可能 可能 可能 可能 可能
已提交读 == Degree 2 不可能 不可能 可能 可能 可能 可能 可能 可能
游标稳定性 不可能 不可能 不可能 有时可能 有时可能 可能 可能 有时可能
可重复读 不可能 不可能 不可能 不可能 不可能 可能 不可能 不可能
快照 不可能 不可能 不可能 不可能 不可能 有时可能 不可能 可能
ANSI SQL SERIALIZABLE == Degree 3 == Repeatable Read Date, IBM, Tandem, … 不可能 不可能 不可能 不可能 不可能 不可能 不可能 不可能

892bbc67c6ee6df0cfec9c833135bfe.png