主要内容
事务(transaction)是一系列的数据库操作,是数据库应用程序的基本逻辑单元。事务处理技术主要包括数据库恢复技术和并发控制技术。数据库恢复机制和并发控制机制是数据库管理系统(DBMS)的重要组成部分。
事务的基本概念
事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。
在关系数据库中,一个事务可以是一条或一组SQL语句,甚至是整个程序。事务与程序是两个概念,一般一个程序中包含多个事务。
事务的开始和结束可以由用户显式控制。如果用户没有显式定义,DBMS会按默认规定自动划分事务。
定义事务的三条SQL语句:
BEGIN TRANSACTION;
COMMIT; /*提交事务的所有操作,将数据库的更新内容写入物理数据库中*/
ROLLBACK; /*撤回事务的所有操作,将数据库恢复到事务开始时的状态*/
事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。
事务的ACID特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability)。
(1)原子性:事务中的所有操作,要么全部都做,要么全部不做。
(2)一致性:若事务在执行过程中被中断,就会出现部分更新被写入物理数据库,而部分操作未被执行的情况。事务的不完全执行可能使得数据库处于一种不确定,不一致的状态。例如在甲对乙的转账操作中,甲转账后操作被中断,甲少了一笔钱,乙却没有得到那笔钱,这样就不符合事务执行的理想结果。可见,事务的一致性和原子性是密切相关的。
(3)隔离性:并发执行的各个事务之间不能互相干扰。
(4)持续性:一个事务一旦提交,它对数据库中数据的改变是永久的。
保护事务的ACID特性正是DBMS中数据恢复机制和并发控制机制的责任。
故障的种类
1. 事务内部的故障
事务内部的故障又分为可预期和不可预期的故障。
对于可预期的故障,可以在定义事务的同时定义故障的处理方式。
例如在转账事务中应对转出用户余额不足的情况:
BEGIN TRANSACTION
读入甲的余额BALANCE1;
BALANCE1 = BALANCE1 - AMOUNT; /*AMOUNT为转账金额*/
/*该语句表示先转账*/
IF(BALANCE1 < 0) THEN
{
打印'余额不足,不能转账';
ROLLBACK; /*如果余额不足,撤回刚才的转账操作*/
}
ELSE
{
读入乙的余额BALANCE2;
BALANCE2 = BALANCE2 + AMOUNT;
写入BALANCE1、BALANCE2;
COMMIT; /*提交操作*/
}
实际上,事务内部更多的故障是不可预期的,这些故障不能由应用程序来处理。
事务故障意味着事务未被完全执行,因此数据库可能处于不一致(不确定)状态。恢复程序要在不影响其他事务的情况下,撤回(UNDO)该事务。
2. 系统故障
系统故障是指造成系统停止运转的任何事件,其中最常见的情况就是电脑强制关机、台式电脑被断电等(超级心痛的…)。除此之外还包括硬件故障、操作系统故障等。
这类故障影响所有正在执行或未被写入物理数据库的事务,其中包括未完成的事务和已完成的事务。
未完成的事务可能有部分操作结果被写入物理数据库,使数据库处于一种不确定的状态。为保证一致性,需要强行回滚(UNDO)该类事务。
已完成的事务可能有一部分甚至全部操作结果保存在缓冲区中,而发生系统故障时,缓冲区的内容会全部丢失,这同样会使数据库处于一种不确定的状态,所以应该重做(REDO)此类事务。
3. 介质故障
介质故障指外存故障,如磁盘损坏、磁头碰撞、瞬时强磁场干扰等。这类故障会破坏数据库,并影响所有与被破坏数据库有关的事务。这类故障比前两类故障发生的可能性小,但破坏性最大。
4. 计算机病毒
计算机病毒的种类很多,小的只有20条指令,不到50B,大的可以像一个操作系统,由上万条指令组成。
数据库恢复技术
恢复的基本原理非常简单:冗余。数据库中任何一部分被破坏或不正确的数据可以根据存储在系统别处的冗余数据来重建。
建立冗余数据最常用的技术是数据转储和登记日志文件。
数据转储
数据库管理员定期地把整个数据库复制到磁带、磁盘或其他存储介质上保存起来。这些备用的数据称为后备副本(backup)。
当数据库遭到破坏后,可以将后备副本重新装入,但重装后备副本只能将数据库恢复到转储完毕时的状态(进行转储需要一个时间段),想要恢复到故障发生时的状态,必须重新运行自转储以后的所有更新事务。
转储十分耗费时间和资源,不能频繁地进行。
转储可以分为静态转储和动态转储:
(1)静态转储:在系统中无运行事务时进行转储操作。静态存储简单,但转储必须等待正运行的用户事务结束才能进行,同样下一个用户事务必须等待转储完毕才能进行。显然,这会降低数据库的利用率。
(2)动态转储:转储期间允许事务运行,允许对数据库的存取或修改。虽然动态转储克服了静态转储的缺点,使得转储和用户事务能并发运行,但是转储完毕时,后备副本保存的数据有可能是过时的。比如上一个时刻刚转储完数据A,下一个时刻就改变了数据A的值,那样重装后备副本时,载入的数据就是不正确的。
因此,必须把转储期间各事务对数据库的修改登记下来,建立日志文件(log file)。这样,后备副本配合上日志文件就能把数据库恢复到某一时刻的正确状态。
转储还可以再分为海量转储和增量转储:
(1)海量转储:转储整个数据库;
(2)增量转储:每次只转储上一次转储后更新过的数据。
从恢复角度来看,海量转储更方便用于恢复。但如果数据库很大,事务处理又十分繁琐,建议使用增量转储。
登记日志文件
日志文件是用来记录事务对数据库的更新操作的文件。不同数据库系统采用的日志文件格式不完全一样。概括起来日志文件主要有两种格式:以记录为单位的日志文件和以数据块为单位的日志文件。
(1)以记录为单位的日志文件需要登记三种日志记录(log record):
1. 各个事务的开始(BEGIN TRANSACTION)标记;
2. 各个事务的结束(COMMIT或ROLLBACK)标记;
3. 各个事务的所有更新操作。
每个日志记录又包括:
1. 事务标识(哪个事务);
2. 操作的类型(插入、删除或修改);
3. 操作对象;
4. 更新前的数据;
5. 更新后的数据。
(2)以数据块为单位的日志文件:
日志记录的内容包括事务标识和被更新的数据块。
由于更新前后的整块数据都放入日志文件中,所以不需要再记录操作类型和操作对象等信息。
登记日志文件的作用以及原则
(1)三个作用:
1. 事务故障和系统故障的恢复必须用到日志文件;
2. 动态转储中必须建立日志文件,后备副本和日志文件结合起来才能有效地恢复数据库;
3. 静态转储中也可以建立日志文件,重装后备副本后,可利用日志文件把已完成的事务进行重做(REDO),并对故障发生时尚未完成的事务作撤销(UNDO)处理。这样不需要重新运行已完成的事务程序就能把数据库恢复到数据库故障前的某一时刻;
*从上面一行文字可以了解到重做和重新运行不是同一个概念。
(2)两个原则:
1. 登记的次序严格按照并发事务执行的时间次序;
2. 必须先写日志文件,后更新数据库。
把对数据的修改写到数据库和把表示这个修改的日志记录写到日志文件中是两个不同的操作。
如果先修改数据库,后写日志文件,以后就无法恢复这个修改了。
恢复策略
事务故障的恢复
事务故障是指事务在运行至正常终点前被终止,这时恢复子系统应利用日志文件撤销(UNDO)此事务对数据库的修改。
(1)反向(从后往前)扫描日志文件,对事务执行逆操作。插入→删除,删除→插入,修改后→修改前;
(2)直至读到事务的开始标记(BEGIN TRANSACTION)。
系统故障的恢复
(1)正向(从前往后)扫描日志文件,找出故障发生前已经提交(COMMIT)的事务,将其事务标识记入重做队列(REDO-LIST),同时将未完成事务的事务标识记入撤销队列(UNDO-LIST)。
(2)对撤销队列中的各个事务进行撤销处理。(如同事务故障的恢复)
(3)对重做队列中的各个事务进行重做处理。正向扫描日志文件,将日志记录中“更新后的值”直接写入数据库。
介质故障的恢复
介质故障是最严重的故障,只能重装数据库,然后重做已完成的事务。
(1)装入最新的数据库后备副本(静态转储),使数据库恢复到最近一次转储时的一致性状态;
对于动态转储的后备副本,还需要装入日志文件,利用恢复系统故障的方法才能将数据库恢复到一致性状态。
(2)装入日志文件,重做已完成的事务。
利用检查点技术的恢复策略
为什么要引入检查点?
一方面是恢复数据库时扫描整个日志文件将耗费大量时间,另一方面是很多需要重做的事务实际上已经将更新操作结果写入数据库中,恢复子系统重新执行又浪费了大量时间。
引入检查点(checkpoint)记录,增加一个重新开始文件,并让恢复子系统在登记日志文件期间动态地维护(更新)日志,这样可以大大提高恢复数据库的效率。
恢复数据库时,恢复子系统将根据事务的不同状态采取不同的恢复策略。
(1)不执行操作:
T1:在检查点前提交
(2)执行重做操作:
T2:在检查点前开始执行,在检查点后、故障点前提交
T3:在检查点后开始执行,在故障点前提交
(3)执行撤销操作:
T4:在检查点前开始执行,在故障点后提交
T5:在检查点后开始执行,在故障点后提交
数据库镜像
根据数据库管理员的要求,自动把整个数据库或其中的关键数据复制到另一个磁盘上,每当主数据库更新时,DBMS自动把更新的数据复制过去。
数据库镜像是通过复制数据实现的,频繁的复制操作自然会降低系统运行效率,因此在实际应用中,用户往往只选择对关键数据和日志文件进行镜像。