文章目录
- 📚事务的概念
- 🐇事务定义
- 🐇事务界定
- 🐇事务特性(ACID)
- 🐇一个简单的事务模型
- 📚存储器结构
- 📚事务的原子性和持久性
- 🐇几种常见的事务状态
- 🐇事务所处状态(必须处于以下之一)
- 📚事务的隔离性
- 🐇并发的意义
- 🐇并发的问题
- 📚可串行化⭐️
- 🐇调度
- 🐇串行调度
- 🐇串行等价
- 🐇可串行化的概念
- 🐇冲突可串行化
- 🥕非冲突操作
- 🥕冲突操作
- 🥕冲突等价
- 🥕冲突可串行化
- 🐇视图可串行化(难)
- 🥕视图等价
- 🥕视图可串行化
- 📚事务的隔离性和原子性
- 🐇可恢复调度
- 🐇无级联调度
- 📚事务的隔离性级别
- 📚小结
- 👀应试
- 👀参考博客
📚事务的概念
🐇事务定义
访问并可能更新各种数据项的一个程序执行单元(可能是一组操作序列、一个或一段应用程序)
🐇事务界定
begin transaction
开始事务commit
表示事务成功结束,对数据库的更新交付实施rollback
表示事务不成功结束,对数据库的更新撤消,数据库恢复该事务到初始状态。end transaction
结束事务
🐇事务特性(ACID)
- 原子性:一个事务是一个不可分割的工作单位,要么执行其全部操作,要么就根本不执行
- 一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。当数据库成功提交事务的结果时,就说数据库处于一致性状态
- 隔离性:一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对并发的其它事务是隔离的,并发执行的各个事务之间不能相互干扰,如有干扰,要加隔离机制
- 并发控制以事务为单位进行的
- 持续性:持续性也称永久性, 是指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后面的其它操作或故障不应对其有任何影响
- ACID之间的关系❓
- 原子性要求事务的所有操作作为一个整体,修改A与修改B两个操作要么全做,要么全不做
- 事务执行过程中的暂时不一致性,不能影响事务的最后结果,原子性保证了事务的一致性
- 持久性要求成功提交后,对数据库的更新是永久的,由恢复系统保证
- 原子性和持久性由恢复系统保证
🐇一个简单的事务模型
-
read(X)
:从数据库中将数据项X读到内存的缓冲区 -
write(X)
:从内存的缓冲区将数据X写回数据库,执行commit成功写回,执行rollback写回操作撤消 -
一个简单的事务模型
从帐号A取50元,存入帐号B,记为事务T
- 一致性:此例一致性要求事务T的执行结果保证数据库中A和B的和不变
- 原子性:假设故障发生在write(A)之后write(B)之前。个账导致丢失¥50,数据不一致
- 持久性:事务T一旦执行完成,用户被告知资金转账已经发生,系统必须保证任何故障都不会引起这次转账的数据丢失
- 隔离性:T修改完A后,出现暂时不一致状态,此时第二个事务插进来计算A与B的和,会得错误结果,第三个事务插进来修改A、B的值,也造成错误
📚存储器结构
- 易失性存储器
- 驻留在易失性存储器中的信息通常在系统崩溃后不会幸存。
- 这种存储器的示例包括主存储器和高速缓冲存储器,访问速度快
- 非易失性存储器
- 驻留在非易失性存储器中的信息会在系统崩溃后幸免于难。
- 非易失性存储器的示例包括磁盘和闪存那样的二级存储设备,以及光盘和磁带那样的三级存储设备,访问速度慢
- 稳定存储器:
- 驻留在稳定存储器中的信息永远不会丢失(应该对永远不会持有保留态度,因为理论上的永远不会是不能保证的。例如,尽管可能性非常小,也有可能出现黑洞吞噬地球从而永久地销毁所有数据!(笔者发出了哇塞的声音))
- 为了实现稳定存储器,我们可以将信息复制到几个非易失性存储器介质(通常是磁盘)中,这些介质采用独立的故障模式
📚事务的原子性和持久性
🐇几种常见的事务状态
- 中止:事务未能成功执行(如果要确保原子性,中止的事务必须对数据库的状态不造成影响)
- 已回滚:中止的事务造成的变更已被撤销
- 日志:事务对数据库所做的每个修改都会首先被记录到日志中(对日志的维护提供了通过重做修改来保证原子性和持久性的可能,以及在事务执行期间发生故障的情况下通过撤销修改来保证原子性的可能)
- 已提交:成功完成其执行的事务。一旦事务已经提交,我们不能通过中止它来撤销其造成的影响
- 补偿事务:撤销已提交事务所造成的影响
- 终止:如果一个事务要么是提交的要么是中止的,它就被称为是已经终止的
🐇事务所处状态(必须处于以下之一)
- 活跃状态,为初始状态,当事务执行时就处于这种状态
- 部分提交状态,在最后一条语句被执行之后
- 失效状态,在发现正常执行不能再继续之后
- 中止状态,在事务已回滚并且数据库已被恢复到它在事务开始前的状态之后。仅当一个事务已进入中止状态,我们才说该事务已中止
- 提交状态,在成功完成之后。只有在一个事务已进入提交状态后,我们才说该事务已提交
📚事务的隔离性
事务处理系统通常允许多个事务并发地执行,保证所执行的任何调度都能使数据库处于一致状态,是DBS中的并发控制部件的任务
🐇并发的意义
- 数据库资源是共享的,应允许多个用户并行地存取数据库
- 提高吞吐量和资源利用率;减少等待时间
- 并发操作不加控制会导致存取不正确性,破坏数据库的一致性
🐇并发的问题
- 串行执行正确的事务,并发执行可能会出现错误
- 控制并发事务相互影响且确保不因并发出现错误
- 并发执行产生的数据不一致性
-
丢失修改:事务2的提交结果破坏了事务1提交的结果,导致事务1的修改被丢失
- 数据库中A的值最后正确的结果
◦ T1→T2,为140
◦ T2→T1,为170
◦ T1修改的结果被T2插入后丢失了
- 数据库中A的值最后正确的结果
-
不可重复读:指事务2读取数据后,事务1执行更新操作,使事务2无法再现前一次读取结果
- T2读A值正确的结果
◦ T1→T2,两次都为70
◦ T2→T1,两次都为100
◦ 现在是一次100,一次70
- T2读A值正确的结果
-
读“脏”数据:由于事务1被撤消,这时事务1已修改过的数据恢复原值,事务2原先读到的数据就与数据库中的数据不一致,是不正确的数据,又称为“脏”数据
- T2读A值正确的结果
◦ T1→T2,为100
◦ T2→T1,为100
◦ 现在是70
- T2读A值正确的结果
-
脏写:如果一个数据项已经被另外一个尚未提交或中止的事务写过,则不允许对该数据项再执行写操作
-
📚可串行化⭐️
🐇调度
- 一组事务的一个调度必须包含这些事务的全部指令,则称这组事务为调度
- 写成read、write操作的序列
🐇串行调度
- 属于同一事务的指令在调度中邻接执行n个事务的事务组,有n!个串行调度
- 例如 ,T1 ,T2,T3三事务,有
3!=6
种串行调度:T1→T2→T3
,T1→T3→T2
,T2→T1→T3
,T2→T3→T1
,T3→T1→T2
,T3→T2→T1
- 例如 ,T1 ,T2,T3三事务,有
🐇串行等价
- 在并发执行中,通过保证所执行的任何调度效果都与没有并发执行的调度效果一样,可以确保数据的一致性
- 即并发执行与串行执行的效果一样,没有发生错误
🐇可串行化的概念
- 多个事务并发执行的结果,和这组事务的某一个串行调度执行结果一致
执行结果一致❓
- 包括最终对数据库的影响
- 包括对各事务运行的影响
- 包括事务read到的值的影响
- 可串行化是并发执行正确性的判定标准
- 当且仅当调度是可串行化的时,并发调度是正确的
🐇冲突可串行化
🥕非冲突操作
- 考虑一个调度S,S中含有分别属于事务Ti和Tj的两条连续指令I和J,以下两种情况为非冲突操作,因为交换I和J不会影响指令结果
- Ti,Tj 对不同数据的读写操作
- Ti,Tj对同一数据Q的读操作:
I=read(Q)
,J=read(Q)
🥕冲突操作
- 考虑一个调度S,S中含有分别属于事务Ti和Tj的两条连续指令I和J,以下三种情况为冲突操作,因为交换I和J会影响指令结果
- 读写操作:
I=read(Q)
,J=write(Q)
- 写读操作:
I=write(Q)
,J=read(Q)
- 写写操作:
I=write(Q)
,J=write(Q)
- 读写操作:
🥕冲突等价
- 非冲突操作可以交换,不影响结果
- 冲突的操作不能交换,交换产生的结果不同
- 令I与J是调度S的连续指令,若I与J是属于不同事务的指令且I与J并不冲突,则可以交换I与J的次序来产生一个新的调度S’,称S与S’冲突等价
🥕冲突可串行化
- 概念:若一个调度S与一个串行调度S’是冲突等价的,则称调度S是冲突可串行化的
- 优先图(也称前驱图,顺序图)判断法
-
优先图是一个关于调度S的有向图
G=(V,E)
- V是顶点集,由参与到调度中的所有事务组成
- E是边集,边集由满足先I=read(Q)后J=write(Q),先I=write(Q)后J=read(Q),先I=write(Q)后J=write(Q) 这三个条件之一的所有Ti→Tj的边组成
-
若图无环,S是冲突可串行化的
-
等价的串行调度是,按有向边出口依次截取结点
-
🐇视图可串行化(难)
🥕视图等价
- 两个调度S、S’满足
- ①对每个数据项Q的初值,在两个调度中是由同一个事务读产生的(S读Q的初值, S’也必须读Q的初值)
- ②事务Ti读取的Q值,在两个调度中,都是由同一个事务写产生的(S读了写操作后的值, S‘也必须读同样写操作后的值)
- ③Q的终值,在两个调度中是由同一个事务写
- 则称S与S’是视图等价
- 条件①②保证两个调度中的每个事务都读取相同的值,从而进行相同的计算
- 条件①②③保证两个调度得到最终相同的系统状态
🥕视图可串行化
-
概念:若一个调度S与一个串行调度S’是视图等价的,则S是视图可串行化的
-
冲突可串行调度一定是视图可串行化的
-
存在视图可串行化但非冲突可串行化的调度
-
-
扩展优先图
- 原理
- 对于先I=write(Q)后J=read(Q) ,意味着等价的串行调度是Ti→Tj
- 如果有一个K=write(Q)存在,Tk要么在Ti之前,要么在Tj之后,否则就不是等价 Ti→Tj
- 假定Tk在Ti之前,加一条边Tk→Ti;假定Tk在Tj之后,加一条边Tj→Tk
- 对于先I=write(Q)后J=read(Q) ,意味着等价的串行调度是Ti→Tj
- 扩展优先图(带标记)判断
-
读写操作序列
- T1,T2,…Ti,…Tj…表示为结点
- 对调度S增加两个虚事务:设调度S包含了事务{T1, T2, … , Tn},设Tb, Tf是两个虚事务,其中Tb为S中所有write(Q)操作, Tf为S中所有read(Q)操作。在调度S的开头插入Tb ,在调度S的末尾插入Tf,得到一个新的调度S
- 头事务Tb只有写操作
B=write(Q)
- 尾事务Tf只有读操作
F=read(Q)
- 调度S写成读写操作序列
S'=(B=write(Q) ... ... F=read(Q))
- 头事务Tb只有写操作
-
⭐️如果无(有向)环,是视图可串行化的调度⭐️
-
⭐️如果去掉P标记边对的一条,无(有向)环,也是视图可串行化调度⭐️
-
⭐️等价的串行调度是,按有向边出口依次截取结点⭐️
-
- 原理
📚事务的隔离性和原子性
🐇可恢复调度
- 不可恢复性调度:需要恢复时,因为部分调度已经中止,而导致调度无法恢复至原状态
• 示例:如果T1在R(B)之后,希望rollback,则无法处理,因为T2已经提交 - 可恢复性调度:对每对事务Ti和Tj,如果Tj读了之前由Ti写的数据,则Ti 必须先于Tj提交
• 示例:如果需要rollback,则调度重新开始即可
🐇无级联调度
- 级联回滚:因单个事务失效而导致一系列事务回滚的现象称为级联回滚
- 无级联调度:不会出现级联回滚的调度,称无级联调度(避免大量回滚操作)
- 措施:如果 T j T_j Tj要读 T i T_i Ti写的数据,则 T j T_j Tj必须等 T i T_i Ti提交完成后再读(即:不读脏数据)
📚事务的隔离性级别
- 为提高并发度,可采用较弱级别的一致性(SQL标准规定的隔离性级别)
- 可串行化:通常保证可串行化的执行。一些数据库系统以在某些情况下可能允许非可串行化执行的方式来实现这种隔离性级别
- 可重复读:只允许读取已提交的数据,并进一步要求在一个事务两次读取一个数据项期间,其他事务不得更新该数据项。但是,该事务对于其他事务来说可能不是可串行化的。例如,当一个事务在查找满足某些条件的数据时,它可能找到一些由一个已提交事务所插入的数据,但可能找不到由同一个事务所插入的其他数据
- 已提交读:只允许读取已提交数据,但并不要求可重复读。例如,在事务两次读取一个数据项期间,另外的事务可以更新该数据项并提交
- 未提交读:允许读取未提交数据。这是SQL允许的最低隔离性
- 以上所有的隔离性级别附带都不允许脏写,即如果一个数据项已经被另外一个尚未提交或中止的事务写过,则不允许对该数据项再执行写操作
- 隔离性级别的实现
- 并发控制(详见第十四章)
- 锁(两阶段封锁协议)
- 时间戳(读时间和写时间)
- 基于有效性检查的协议
- 多版本和快照隔离
📚小结
👀应试
方法:
- E是边集,边集由满足先I=read(Q)后J=write(Q),先I=write(Q)后J=read(Q),先I=write(Q)后J=write(Q) 这三个条件之一的所有Ti→Tj的边组成
- 若图无环,S是冲突可串行化的
- 等价的串行调度是,按有向边出口依次截取结点
👀参考博客
如何画前趋图?
视图可串行化
冲突可串行化