1、事务的概念及特性事务的概念及特性事务的操作事务的操作 计算机系统故障是不可避免的。发生故障的原因多样,如硬计算机系统故障是不可避免的。发生故障的原因多样,如硬件故障、恶意破坏等。一旦故障发生,会对数据库中的数据造成件故障、恶意破坏等。一旦故障发生,会对数据库中的数据造成破坏,因此,破坏,因此,DBMS必须采取措施,以保障即使发生故障,也必必须采取措施,以保障即使发生故障,也必须使数据库恢复到故障发生前的某一个状态,称为系统恢复技术。须使数据库恢复到故障发生前的某一个状态,称为系统恢复技术。1.单单纯纯以后备复本为基础的恢复技术以后备复本为基础的恢复技术2.以后备复本和运行记录为基础的恢复技术以
2、后备复本和运行记录为基础的恢复技术(1)前前像像当当数据库被一个事务更新时,所涉及的数据库被一个事务更新时,所涉及的物理物理块被更新块被更新前前的的映像称为该事务的前像映像称为该事务的前像。(2)后像后像 当数据库被一个事务更新时,所涉及的物理块被更新后当数据库被一个事务更新时,所涉及的物理块被更新后的映像称为该事务的后像。的映像称为该事务的后像。数据库的表结构:数据库的表结构:Student(StuID,StuName,StuAge,StuSex,StuCity,StuScore,DepID)Department(DepID,DepName,Total)判断以下事务的前像、后像各是什么?判断
3、以下事务的前像、后像各是什么?事务事务T将学生将学生A00001从从1系转入系转入2系,有系,有3个操作组成:个操作组成:update student set DepID=2 where StuID=A00001update Department set Total=Total+1 where DepID=2update Department set Total=Total-1 where DepID=1update student set DepID=2 where StuID=A00001update Department set Total=Total-1 where DepID=1up
4、date Department set Total=Total+1 where DepID=2DepID=1前像前像后像后像DepID=2Total=100Total=100Total=99Total=101操作操作操作操作操作操作tDepID=1前像前像后像后像DepID=2Total=100Total=100Total=99Total=101操作操作操作操作操作操作t 保存保存COMMIT故障故障undo操作操作:以前像为参照,反向扫描日志,做逆操作恢复数据。以前像为参照,反向扫描日志,做逆操作恢复数据。执行执行commit前数据已保存到数据库,但此时还未执行前数据已保存到数据库,但此时还
5、未执行commit发生了故障;发生了故障;DepID=1前像前像后像后像DepID=2Total=100Total=100Total=99Total=101操作操作操作操作操作操作tCOMMIT 保存保存故障故障redo操作操作:以后像为参照,正向扫描日志,做正操作恢复数据。以后像为参照,正向扫描日志,做正操作恢复数据。执行执行commit后数据才会被保存到数据库,但在后数据才会被保存到数据库,但在commit之后保存数据库之前发生了之后保存数据库之前发生了故障;故障;3.基于多副本的恢复技术基于多副本的恢复技术 如果系统中有多个数据库副本,可以利用这些副本互为备如果系统中有多个数据库副本,可
6、以利用这些副本互为备份,用于恢复。常用于分布式数据库系统中。份,用于恢复。常用于分布式数据库系统中。读数据时,可以选择其中任一个结点上的数据;读数据时,可以选择其中任一个结点上的数据;写数据时,每个结点都写入同样的内容。写数据时,每个结点都写入同样的内容。有某数据库系统在运行过程中发生了系统故障,发生故障时正有某数据库系统在运行过程中发生了系统故障,发生故障时正在运行事务在运行事务t1和和t2。进行故障恢复时,在日志文件中发现有。进行故障恢复时,在日志文件中发现有t1事事务的开始记录而没有结束记录;有务的开始记录而没有结束记录;有t2的开始记录和结束记录,但的开始记录和结束记录,但t2对数据库
7、的修改还没有写到数据库中。如何恢复数据库到一致对数据库的修改还没有写到数据库中。如何恢复数据库到一致状态?状态?Tc(保存点保存点)Tf(系统故障系统故障)REDOUNDOUNDO REDOT2T3T4T5什么都不做什么都不做T1写一个事务执行售票点售票功能。每个售票点售票完成需要写一个事务执行售票点售票功能。每个售票点售票完成需要2个步骤,个步骤,首先查看数据库中票的张数是否大于首先查看数据库中票的张数是否大于0,如果大于,如果大于0,则售票后更新数,则售票后更新数据库票的张数。售票信息存在表据库票的张数。售票信息存在表Ticket(TicketInfo,TicketLeaveNum)中。中
8、。解决方案:解决方案:CREATE PROC prcSellTicketTicketInfo varchar(20),-车次信息车次信息TicketNum int -售出张数售出张数ASBegin tranDeclare TicketLeaveNum intSelect TicketLeaveNum=TicketLeaveNum from TicketWhere TicketInfo=TicketInfo -waitfor delay 00:00:20Update Ticket set TicketLeaveNum=TicketLeaveNum TicketNumWhere TicketInf
9、o=TicketInfo -If(TicketLeaveNum TicketNum)begin rollback tran print 售票失败售票失败 endElse begin Commit tran print 售票成功售票成功 endTicketT001,16售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻时刻4read,16read,16 16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB16-1=15,write to DBTicketT001,15售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻
10、时刻3时刻时刻4read,16read,16 16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB 多个用户在执行相同的事务时,会导致数据库中的数多个用户在执行相同的事务时,会导致数据库中的数据发生错误信息,这种情况称为事务的并发。据发生错误信息,这种情况称为事务的并发。多个用户在执行相同的事务时,事务会产生并发情况,多个用户在执行相同的事务时,事务会产生并发情况,从而导致数据库中的数据发生错误信息,实际中我们应该从而导致数据库中的数据发生错误信息,实际中我们应该考虑到并发的存在,并试图解决这种
11、并发情况。考虑到并发的存在,并试图解决这种并发情况。解决方案:解决方案:1.锁机制锁机制2.设置事务的隔离级别设置事务的隔离级别共享锁共享锁排他锁排他锁 共享锁又称为读锁、共享锁又称为读锁、S锁。锁。又称为写锁、又称为写锁、X锁。锁。T1 SXSYNXNNX锁、锁、S锁的相容矩阵锁的相容矩阵 T2TicketT001,16售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻时刻4时刻时刻5时刻时刻6获得获得X锁锁 read,16 获得获得X锁锁 read,15 16-1=15,write to DB16-1=15,write to DB commit commit 释放释放x x锁
12、锁事务事务TA事务事务TB申请申请X锁锁等待等待等待等待等待等待15-1=14,write to DB15-1=14,write to DB commit commit 释放释放x x锁锁 TicketT001,16售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻时刻4时刻时刻5时刻时刻6获得获得S锁锁 read,16(释放(释放S S锁)锁)释放释放S锁锁 16-1=15,write to DB16-1=15,write to DB commit commit 事务事务TA事务事务TB申请申请S锁锁获得获得S锁锁read,1616-1=15,write to DB16-1=1
13、5,write to DB commit commitCREATE PROC prcSellTicketTicketInfo varchar(20),-车次信息车次信息TicketNum int -售出张数售出张数ASBegin transelect TicketLeaveNum from Ticket with(tablockx)Declare TicketLeaveNum intSelect TicketLeaveNum=TicketLeaveNum from TicketWhere TicketInfo=TicketInfo -waitfor delay 00:00:20.005Upda
14、te Ticket set TicketLeaveNum=TicketLeaveNum TicketNumWhere TicketInfo=TicketInfo -If(TicketLeaveNum TicketNum)begin rollback tran print 售票失败售票失败 endElse begin Commit tran print 售票成功售票成功 end为为Ticket表加排他锁表加排他锁(1)未提交读)未提交读(read uncommitted)(2)已提交读)已提交读(read committed)(3)可重复读)可重复读(repeatable read)(4)可序列
15、化)可序列化(serializable)当前事务当前事务其他事务其他事务读读能读,能修改能读,能修改修改修改能读,不能修改能读,不能修改规则:规则:售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻时刻4read,16read,16 16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB事务事务TA事务事务TB当前事务当前事务其他事务其他事务读读能读,能修改能读,能修改修改修改不能读,不能修改不能读,不能修改规则:规则:售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻
16、时刻4read,16read,16 16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB16-1=15,write to DB事务事务TA事务事务TB当前事务当前事务其他事务其他事务读读能读,不能修改能读,不能修改修改修改不能读,不能修改不能读,不能修改规则:规则:售票点售票点A售票点售票点B时刻时刻1 时刻时刻2时刻时刻3时刻时刻4read,16read,16 等待等待等待等待事务事务TA事务事务TB当前事务执行完另一事务才能开始,可解决所有并发情况。当前事务执行完另一事务才能开始,可解决所有并发情况。隔离级别隔离级别脏读脏读 丢
17、失更新丢失更新 不可重复读不可重复读幻读幻读未提交读未提交读是是是是是是是是已提交读已提交读否否是是是是是是可重复读可重复读否否否否否否是是序列化序列化否否否否否否否否设置隔离级别:设置隔离级别:set transaction isolation level 隔离级别隔离级别CREATE PROC prcSellTicketTicketInfo varchar(20),-车次信息车次信息TicketNum int -售出张数售出张数ASBegin tranDeclare TicketLeaveNum intSelect TicketLeaveNum=TicketLeaveNum from Ti
18、cketWhere TicketInfo=TicketInfo -waitfor delay 00:00:20.005Update Ticket set TicketLeaveNum=TicketLeaveNum TicketNumWhere TicketInfo=TicketInfo -If(TicketLeaveNum TicketNum)begin rollback tran print 售票失败售票失败 endElse begin Commit tran print 售票成功售票成功 endset transaction isolation level repeatable read
19、T1read A=1000 A=A-50 write Aread B=2000 B=B+50 write B T2 read A=950 T=50 A=A-T write Aread B=2050 B=B+T write B T1read A=1000 A=A-50 write A read B=2000 B=B+50 write B T2 read A=950 T=50 A=A-T write A read B=2050 B=B+T write B 并非所有并行执行的多个事务都会产生并发情况,如并非所有并行执行的多个事务都会产生并发情况,如果多个事务同时执行并不会产生并发错误,那么加上锁或果
20、多个事务同时执行并不会产生并发错误,那么加上锁或隔离级别会降低执行效率。如何有效地判断多个事务是否隔离级别会降低执行效率。如何有效地判断多个事务是否会并发呢?会并发呢?事务并发产生的错误主要有三类:丢失更新、不可重复事务并发产生的错误主要有三类:丢失更新、不可重复读和脏读。读和脏读。T1read A=16 A=A-1 write A T2 read A=16 A=A-1 write A思考:思考:丢失更新的根源是什么丢失更新的根源是什么?结论:结论:在事务提交前的同一个时间段出现了多个事务的写操作,在事务提交前的同一个时间段出现了多个事务的写操作,会造成并发错误。会造成并发错误。写写-写冲突写
21、冲突 T1read(x)read(x)T2 write(x-1)T1read(x)write(x-1)rollback T2 read(x)结论:结论:一个事务写另一个尚未提交且在读的事务;或一个事务读一个事务写另一个尚未提交且在读的事务;或一个事务读另一个已更新且尚未提交的事务会造成并发错误。另一个已更新且尚未提交的事务会造成并发错误。读读-写冲突写冲突 T1read A=1000 A=A-50 write Aread B=2000 B=B+50 write B T2 read A=950 T=50 A=A-T write Aread B=2050 B=B+T write B T1read
22、A=1000 A=A-50 write A read B=2000 B=B+50 write B T2 read A=950 T=50 A=A-T write A read B=2050 B=B+T write B T1read A=1000 A=A-50 write Aread B=2000 B=B+50 write B T2 read A=950 T=50 A=A-T write Aread B=2050 B=B+T write B T1read A=1000 A=A-50 write A read B=2000 B=B+50 write B T2 read A=950 T=50 A=A-
23、T write A read B=2050 B=B+T write BDBMS把把可串行可串行化作为并发控制正确性的准则化作为并发控制正确性的准则!判断是否可串行化的方法是判断是否可串行化的方法是前趋图。前趋图。T1read(A)write(A)read(B)write(B)read(B)T2read(A)write(A)wirte(B)read(B)冲突冲突冲突冲突不冲突不冲突不冲突不冲突 T1read x T2read ywirte x T3write y write xwrite z T4read zwrite x前趋图前趋图调度序列:调度序列:解决方案:解决方案:(1)找出冲突操作对:
24、找出冲突操作对:T1T2T3T4调度序列:调度序列:解决方案:解决方案:T1T2T3T4 T1read A=16 A=A-1 write A T2 read A=16 A=A-1 write A思考:使用前趋图判断思考:使用前趋图判断T1和和T2事务能否并发完成?事务能否并发完成?某航空售票系统负责所有本地起飞航班的机票销售,并设有某航空售票系统负责所有本地起飞航班的机票销售,并设有多个机票销售网点,各售票网点使用相同的售票程序。假设有多个机票销售网点,各售票网点使用相同的售票程序。假设有两个旅客在两个不同的机票销售网点同时预定同一个航班两个旅客在两个不同的机票销售网点同时预定同一个航班A的机
25、的机票票x,则:,则:Ri(x)表示某个机票销售网点读剩余机票数)表示某个机票销售网点读剩余机票数x;Wi(x-j)表示某个机票销售网点售出)表示某个机票销售网点售出j张机票后修改剩余机票张机票后修改剩余机票数数x;下面是系统对两个并发执行售票事务的三个不同调度,即下面是系统对两个并发执行售票事务的三个不同调度,即A、B、C:A:R1(x),R2(x),W1(x-1),W2(x-2)B:R1(x),R2(x),W2(x-2),W1(x-1)C:R1(x),W1(x-1),R2(x),W2(x-2)(1)假设当前航班假设当前航班A剩余剩余10张机票,分析上述三个调度各自执行张机票,分析上述三个调
26、度各自执行完后的剩余机票数。完后的剩余机票数。(2)指出错误的调度。指出错误的调度。串行调度和并行调度的串行调度和并行调度的区别区别:优点缺点串行调度保证调度结果的正确性不能共享资源并行调度能共享资源调度结果可能出现错误思考:若多个事务同时执行,是否有一种方法既能保证像串行调度那样的思考:若多个事务同时执行,是否有一种方法既能保证像串行调度那样的正确性,又能保证像并行调度那样共享资源?正确性,又能保证像并行调度那样共享资源?两段锁协议:两段锁协议:是指所有的事务必须分两个阶段对数据项加锁和解锁。第一阶段第一阶段是获得封锁的阶段:事务可以申请锁,但不能释放锁。第二阶段第二阶段是释放封锁的阶段:事
27、务可以释放锁,但不能申请锁。T1Lock(A)Read AA=A-50Write ALock(B)Read BB=B+50Write BUnlock(B)Unlock(A)死锁是这样一种情形:两个用户(或事务)在个别的对象的上死锁是这样一种情形:两个用户(或事务)在个别的对象的上锁,并且每个用户正在等待另一个对象的锁。两个事务处于无锁,并且每个用户正在等待另一个对象的锁。两个事务处于无限制的等待状态中,称为死锁。限制的等待状态中,称为死锁。事务事务1事务事务2资源资源1资源资源21.设置死锁优选级设置死锁优选级语法:语法:SET DEADLOCK_PRIORITY LOW|NORMAL|deadlock_var2.设置等待被阻塞资源的最长时间设置等待被阻塞资源的最长时间语法:语法:SET LOCK_TIMEOUT timeout_period活锁是这样一种情形:若某数据对象加了活锁是这样一种情形:若某数据对象加了S锁,这时若有其他锁,这时若有其他事务申请对它的事务申请对它的X锁,则必须等待。如果不断有事务申请对此锁,则必须等待。如果不断有事务申请对此数据对象的数据对象的S锁,以致它始终被锁,以致它始终被S锁占有,而锁占有,而X锁定申请迟迟不锁定申请迟迟不能获准。能获准。解决方案:解决方案:先申请,先服务。先申请,先服务。