1、第五章 事务,事务:是构成单一逻辑工作单元的操作集合。如:从支票帐户到储蓄帐户的资金转帐是一次顾客看到的单独操作。数据库系统的角度,这是由几个操作完成的。,51 事务概念,52 事务状态,53 原子性和持久性的实现,54 并发执行,55 可串行化,56 可恢复性,57 隔离性实现,58 可串行化的判定,51 事务概念,事务是访问并可能更新各种数据项的一个程序执行单元, 由高级数据操作语言或编程语言(如 SQL COBOL C等)的用户程序的执行引起, 用begin transaction 和end transaction 来界定, 由事务开始与结束之间执行的全体操作组成。,为了保证数据完整性,
2、 数据库系统必须做到:,原子性(atomicity):事务的所有操作在数据 库中要么全部正确反映出来要么全部不反映。一致性(consistency):事务隔离执行 时(即 没有并发执 行的其他事务)保持数据库的一致性。,隔离性(isolation):尽管多个事务可以并发 执行,但系统必须保证对任一事务对Ti和Tj,在Tj看来,Tj或者在Ti开始之前已经停止执行,或者在Ti完成之后开始执行。这样,每个事务都感觉不到系统中有其他事务在并发的执行。持久性(durability):一个事务成功完成后, 它对数据库的改变必须是永久的,即使系统可能出现故障。 这些属性通常称为ACID特性,例:设Ti是从帐
3、户A过户$ 50到帐户B的事 务,事务Ti 。Ti: read(A); A:=A-50; Write(A); Read(B); B:=B+50; Write(B).,一致性原子性持久性隔离性,52 事务状态,事务状态图 :,中止事务:必须对数据库的状态不造成影响, 回滚成功完成: 提交,53 原子性和持久性的实现,1 保证原子性和持久性的影子拷贝技术, 如图:,(1)如果事务故障在db-pointer指针修改之前发生,数据库的原始内容未受影响,通过删除数据库的新拷贝来中止事务。一旦事务已提交,所有更新都在db-pointer指针所指向的数据库中,这样更新事务或全部反映或全不反映。(2)db-p
4、oint写到磁盘之前出现故障,系统重启,得到旧值。db-point写到磁盘之后出现故障系统故障不破坏盘上的内容得到新值。(3)写操作是原子性的,要么全写,要么不写。,2 文本编辑的事务,54 并发执行,数据的并发执行与操作系统中使用的多道程序动机一样。,(1)可以减少不可预测的事务执行时延 (2)减少平均响应时间,事务并发执行的可行性:(1)I/O和CPU(2)各事务针对数据库的不同部分进行 操作。,例:定义两个事务T1,T2 T1过户¥50 T2 10% 从A到B 事务,调度:用于确定那些可以保证一致性的执 行序列。,调度数:n个事务有n!个有效的串行调度 。,例:设T1是从帐户A过户$ 5
5、0到帐户B的事 务,事务T1 T1: read(A); A:=A-50; Write(A); Read(B); B:=B+50; Write(B).,设T2是从帐户A过户10%的存款余额到帐户B的事务,事务T2 T2: read(A); temp=A*0.1 A:=A-temp; Write(A); Read(B); B:=B+temp; Write(B).,调度1T1执行完执行T2,如图:,调度3 、调度4,调度2T2执行完执行T1,如图:,调度3 、调度4,调度3 -等价与调度1的一个并发调度,调度4 - 一个并发调度 ( 数据不一致),55 可串行化,数据库系统必须控制事务的并发执行,保
6、证数据库处于一致的状态。考虑事务中的read与write操作。 1冲突可串行化 2视图可串行化,调度3 -只显示read与write指令,55 . 1 冲突可串行化,考虑调度S,其中含有分别属于Ti与Tj的两条连读指令Ii与Ij(ij)。如果Ii与Ij处理不同数据项,则交换Ii与Ij不会影响调度中任何指令的结果。,下面考虑Ii与Ij处理相同的数据项Q,read(Q),write(Q)有下面四种情形:,(1) Ii = read (Q), Ij = read (Q)。Ii与Ij的次序无关紧 要,因为不论其次序如何,Ti与Tj读取的Q值总 是相同的。 (2) Ii = read (Q), Ij =
7、 write(Q)。若Ii先于Ij,则Ti不会 读取由Tj的指令Ij写入的Q值;若Ij先于Ii,则Ti 读到由Tj的指令Ij写入的Q值。因此Ii与Ij的次序 是重要的。,(3) Ii = write (Q), Ij = read (Q)。Ii与Ij的次序是重要 的,原因类似前一情形。(4) Ii = write (Q), Ij = write (Q)。由于两条指令均为write指令,指令的顺序对Ti与Tj没什么影响。 然而,调度S的下一条read (Q)指令读取的值将 受到影响,因为数据库里只保留了两条write指 令中后一条的结果。如果在调度S中的指令Ii与 Ij之后没有其他的write (
8、Q)指令,则Ii与Ij的顺 序直接影响调度S产生的数据库状态中Q的最终 值。,*冲突: 如图:,T1的write(A)与T2 的read(A)指令冲突。T2的write(A)与T1的read(B)不冲突。,*调度等价:设Ii与Ij是调度S的两条连续指 令,若Ii与Ij属于不同事务且 不冲突,则可以交换Ii与Ij的 顺序得到一个新的调度S,则 S与S等价。,调度5交换调度3的一对指令得到的调度, 如图:,调度6与调度3等价的一个串行调度 , 如图:,调度5 -交换调度3的一对指令得到,调度6-与调度3等价的串行调度,调度7 -不可串行化的调度,冲突等价:若调度S可以经过一系列非冲 突指令交换转换
9、成S,称S与S 是冲突等价。 冲突可串行化:若S与一个串行调度冲突 等价,则称S为冲突可串行化的。, 有可能存在两个调度,它们产生相同的结果,但它们不是冲突等价的,事务T5,从帐户B过户10元到帐户A,如图的调度不与串行调度冲突等价,因为T5的write(B)指令与T1的read(B)指令冲突 因此不能通过交换连续的非冲突指令将T1的所有指令移到T5之前.但是执行调度8或串行调度后,帐户A与B的最终值相同.,调度8,55 . 2 视图可串行化,视图等价:S与S满足三条:对于每个数据项Q,若事务Ti在调度S中读取了Q的初始值,那么Ti在S中也必须读取Q的初始值。 对于每个数据项Q,若事务Ti在调
10、度S中执行了read(Q),并且读取的值是由Tj产生的,那么Ti在S中读取的值也必须由Tj产生。 对于每个数据项Q,若在调度S中有事务执行了最后的write(Q)操作,那么在S中该事务也必须执行最后的write(Q)操作。,视图可串行化:如果某个调度视图等价于一个串行调度,则说这个调度是视图可串行化的。,例: 图:调度9一个视图可串行化调度,等价于,,调度9 -一个视图可串行化调度,冲突可串行化的调度是视图可串行化的。 视图可串行化的调度不一定是冲突可串行化的。,56 可恢复性,前面我们讨论的那些可接受的调度是假定无故障的情况下, 从如何保持数据库一致性出发的。 下面讨论在并发执行过程中事务故
11、障所产生的影响,以撤消它。 如果事务Ti失败了,系统必须撤消Ti的影响以保持事务的原子性。如有并发执行的事务,还必须保证依赖于Ti的任何事务Tj也中止。为此系统还将限制一些调度类型。,1可恢复调度 ,如图:若T9执行完read(A)后立即提交,图中的调度为不可恢复调度。,数据库系统要求调度是可恢复的,即:对于每对事务Ti和Tj,如果Tj读取了Ti所写的数据项,则Ti先于Tj提交。,2无级联调度 ,如图:如果T10失败了,T10回滚,T11依赖于T10,T11也要回滚,T12依赖于T11,T12必须回滚。一个事务的回滚导致一系列事务的回滚的现象称为级联回滚。,无级联调度:对于每个事务Ti和Tj,
12、如果Tj读取了由Ti所写的数据项,则Ti必须在Tj读取前提交。无级联的调度总是可恢复的。,57 隔离性实现,具有冲突可串行化或视图可串行化并且无级联的调度,才能保证数据库的一致性,同时保证事务出现故障时的安全处理。 并发控制机制的目标是获得最高的并发性。同时保证所产生的调度是冲突可串行化或视图可串行化并且无级联的。,58 可串行化的判定,由前面的讨论,调度是否可串行化显得非常重要。因此我们必须知道如何确定一个调度S是否可串行化。 对于冲突可串行化的判定,存在一个简单有效的算法,而判断视图可串行化的简单有效的算法是不存在的。,1 冲突可串行化的判定 设S是一个调度,由S构造一个有向图,称为优先图
13、。 事务-顶点,边由满足下列三条之一的Ti-Tj组成:在Tj执行read(Q)之前,Ti执行write(Q)。在Tj执行write(Q)之前,Ti read(Q)执行。在Tj执行write(Q)之前,Ti执行write(Q)。 如果图中存在边Ti-Tj,则在任何等价于S的串行调度S中,Ti都必须在Tj之前。,优先图中无环,则S是冲突可冲行 化的,用拓扑排序可以判定图中是否 有环。拓扑序列即为串行化顺序。,T1,T1,T1,T1,T2,T2,调度1,调度2,调度4,Ti,Tk,Tj,Ti,Tm,Tk,Tm,Tj,Ti,Tk,Tj,Tm,2 视图可串行化判定:是一个NP完全问 题,因此不存在有效的
14、判定算法。,这节介绍一个判定视图可串行化的方法,该方法对判定冲突可串行化的优先图进行修改,通过在图的边上加标记,确定哪些边必须加入到优先图中,称这样的图为带标记的优先图。即使这样我们会看到判定视图可串行化的计算代价是很高的。,调度9,视图可串行化的调度,视图等价于串行调度。,调度9的优先图,图中有环,因此调度9不是冲突可串行化的。T3,T4的写操作称为无用的写操作,它们产生的值没有被其他的数据项引用。T3-T4不应该加入到图中。需要一种方法判定一条边是否加到优先图中。,T3,T4,T6,设S是一个调度,假定事务Tj读取Ti写入的数据项Q。如果S是视图可串行化的,则在任何与S等价的调度S中Ti必
15、然优先于Tj。现假定在S中Tk执行了write(Q)。则在S中,Tk要么优先于Ti,Tk要么在Tj之后,否则Tj将不能读取Ti写入的数据项Q,则S就不会等价于S。边Tk-Ti和Tj-Tk两者之一必须加入优先图中。下面我们就对加入到优先图中的边加标记来解决这样的问题。,设调度S包含了事务T1,T2,Tn。设Tb与Tf是两个虚事务,设Tb为S中访问的每个Q执行write(Q)操作,Tf为S中访问的每个Q执行read(Q)操作。通过在S的开头插入Tb,在S的末尾加入Tf,可以得到一个新的调度S。用下面的方法构造带标记的优先图。,1)如果事务Tj读取事务Ti写入的数据项Q,则加入边Ti-Tj并带标记0
16、。2)删除所有关联无用事务的边(如果优先图中不存在Ti到Tf的通路,则事务Ti是无用事务)。3)对于每个数据项Q,如果事务Tj读取Ti写入的 Q,Tk执行write(Q)操作且TkTb,则: a.如果Ti=Tb,且TjTf,则在带标记的优先图中插入Tj-Tk标记为0。 b.如果TiTb,且Tj=Tf,则在带标记的优先图中插入Tk-Ti标记为0. c.如果TiTb,且TjTf,则在带标记的优先图中插入Tk-Ti,Tj-Tk标记为p,p是前面未曾用过的大于0的整数。,例:调度7的带标记优先图见P329图13-19,例:调度9的带标记优先图见P329图13-20,例:调度10的带标记优先图见P330图13-22,调度10,