【数据库】数据库恢复技术
数据库恢复技术
实现恢复的核心是使用冗余,也就是根据冗余数据重建不正确数据。
事务
事务是一个数据库操作序列,是一个不可分割的工作单位,是恢复和并发的基本单位。
在关系数据库中,一个事务是一条或多条SQL语句,也可以包含一个或多个程序。一个程序通常包含多个事务。
可以显式的定义一个事务:
BEGIN TRANSACTION SQL 语句1SQL 语句2……
COMMIT|ROLLBACK
COMMIT是提交事务,ROLLBACK是回滚。
事务具有四个非常重要的特性,即ACID特性:
- 原子性(Atomicity) 原子性是指,事务要不全部完成,要不全部取消。如果事务失败,会回滚到事务之前。
- 一致性(Consistency) 一致性是指,只有合法的数据才能写入数据库。
- 隔离性(Isolation) 隔离性是指,如果两个事务同时执行,那么执行顺序不影响执行结果。
- 持续性(Durability) 持久性是指,一旦事务提交,数据必须保存在数据库之中。
事务一般有五种状态,其状态图如下:

故障和恢复
常见的故障有四种:事务内部的故障、系统故障、介质故障、计算机病毒。
事务内部的故障有些是通过事务程序本身发现的,有些是非预期的。比如,有一个事务,从A转账给B。有下面的事务程序:
BEGIN TRANSACTIONBALANCE = BALANCE - 100IF (BALANCE < 0) THEN {ROLLBACK} ELSE {读取用户乙的余额BALANCE1BALANCE1 = BALANCE + AMOUNT写回BALANCE1COMMIT}
如果出现了余额不足,就可以回滚,保证数据库状态正常,而不是只减了甲的钱却不影响乙的钱。
有的时候事务故障是非预期的,比如运算溢出、死锁、违反完整性限制。这类故障一般使用撤销事务(UNDO)。
系统故障是造成系统停止运转的任何事件,使得系统要重新启动。这个时候,系统运行被破坏,事务非正常终止,不破坏数据库,缓存区信息丢失。
这种系统故障可能是硬件错误或操作系统故障引起的。如果发生故障的时候事务未提交,那么直接UNDO未完成事务;如果已提交但缓冲区未写入磁盘,那么进行REDO。
介质故障是外存故障,比如磁盘损坏、磁头碰撞、操作系统潜在错误、瞬时强磁场干扰。一般需要装入介质故障前某个时刻的数据副本,重做所有成功事务。
计算机病毒是人为故障或破坏。
数据转储
一、静态转储和动态转储
在没有运行事务的时候,进行的就是静态转储。转储开始前数据库一致,并且期间不能对数据库进行存取和修改。这种方法实现简单,但是降低了数据库的可用性,因为新的事务必须等转储结束。
如果将转出操作和用户事务并发执行,进行的就是动态转储。转储期间可以进行存取修改,这种方法无需等待正在运行的用户事务,也不会影响新事务运行。但是动态转储不能保证副本中数据的正确性。
因此,做动态转储需要把各事务的修改活动记下来,建立日志,用后备副本加上日志使得数据库恢复。
二、海量转储与增量转储
海量转储是每次转储所有数据库,增量转储是只转储上次转储后的数据。
从恢复角度来看,海量转储更方便,但是数据库很大的时候增量转储更有效。
日志
日志是记录事务对数据库更新操作的文件。
一、日志文件的格式和内容
一般来说,日志有记录为单位,也有以数据块为单位。
以记录为单位的日志内容包含:
- 事务开始标记
- 事务结束标记
- 事务所有更新操作
这样的称为一个日志记录。每条日志记录又分成
- 事务标识(表明事务种类)
- 操作类型(插入、删除、修改)
- 操作对象(记录内部标识)
- 更新前数据的旧值(对插入操作来说是空)
- 更新后数据的新值(对删除操作来说是空)
以数据块为单位的日志文件,每条日志记录内容是
- 事务标识
- 被更新的数据块
二、日志文件的作用
日志文件可以进行事务故障恢复、系统故障恢复、协助后备副本进行介质故障恢复。
下面是一个用静态转储副本和日志文件进行恢复的例子。

在静态转储的基础上,得到一个一致性副本,然后发生故障。那么重新运行所有事务,就可以把数据库恢复到一致状态。
三、登记日志文件
登记日志的次序需要严格按照并行事务执行的时间次序。必须先写日志文件,后写数据库。
这是因为,如果在二者之间故障发生了,先写数据库,这个记录就无法恢复;如果先写日志,只需要做一次UNDO。
四、故障的恢复
(1)事务故障
恢复事务故障,首先反向扫描文件日志,然后查找事务的更新操作。接下来,对事务更新操作进行逆操作,把更新前的值重新写入。
继续扫描文件日志,查找事务其它操作,直到读到事务开始标记。
(2)系统故障
首先正向扫描日志,然后建立两个队列。第一个叫做REDO队列,第二个叫做UNDO队列。REDO队列存放故障发生前的已经COMMIT的事务,UNDO队列存放尚未发生的队列。
对UNDO队列的事务统一进行UNDO处理,也就是在数据库中储存更新前的值;对REDO队列的事务统一做REDO处理,把更新后的值写入数据库。
(3)介质故障
介质故障一般先重装数据库,然后重做已完成的事务。
一般来说,可以装入最新的后备数据库副本。静态副本可以直接装入,动态副本还需要装入转储时的日志文件副本。
介质故障恢复往往需要DBA的介入,重装最近转储的副本和各日志文件副本,执行系统提供的恢复命令。
检查点
之前的日志恢复技术,搜索日志需要大量时间,同时REDO也大量耗费了时间。因此,具有检查点的恢复技术是常见的技术。
建立检查点一般有两种,可以是按固定时间间隔定期建立,也可以按照某种规则,比如日志文件写满一半建立一个检查点。检查点实际上就是一个标记,事务 T T T在检查点之前提交,那么 T T T已经写入了数据库,无需进行REDO。

T3、T5在故障发生时未完成,所以撤销;T2、T4在检查点之后提交,需要REDO;T1则无需REDO。
用检查点的恢复步骤如下:
- 找到最后一个检查点记录的地址
- 由检查点记录得到正在执行的事务ACTIVE-LIST,建立UNDO和REDO LIST,并把ACTIVE LIST放入UNDO LIST
- 正向扫描日志文件,新开始的事务放入UNDO LIST,提交事务放到REDO LIST
- UNDO LIST进行UNDO,REDO LIST进行REDO
数据库镜像
DBMS自动把整个数据库或其中关键数据复制到另一个磁盘上,由DBMS保证镜像数据和主数据库的一致性。在出现介质故障的时候,可以由镜像磁盘继续使用,同时DBMS利用磁盘数据进行恢复,而无需重装数据库副本。

同时,在没有出现故障的时候,数据库镜像也可以用于并发操作,如果一个用户对数据加排他锁,其他用户可以读镜像数据库的数据。
频繁的复制数据会降低效率,所以一般只对关键数据和日志进行镜像。