数据库复习六

# 事务的基本概念

# 一、什么是事务

事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位

  • 事务和程序是两个概念
    • 在关系数据库中,一个事务可以是一条 SQL 语句,一组 SQL 语句或整个程序
    • 一个应用程序通常包含多个事务

事务是恢复和并发控制的基本单位

# 二、如何定义事务

  • 显式定义方式:

    BEGIN TRANSACTION ... COMMIT

    BEGIN TRANSACTION ... ROLLBACK

(1) COMMIT 语句表示:事务正常结束,提交事务的所有操作 (读 + 更新) 事务中所有对数据库的更新永久生效

(2) ROLLBACK 语句表示:事务异常结束,回滚事物的所有更新操作,使事务滚回到开始时的状态

# 三、事务的特性

  • 原子性:事务中包括的诸操作要么都做,要么都不做
  • 一致性:事务执行使数据库从一个一致性到另一致性状态
  • 隔离性:一个事务的执行不能被其他事务干扰,而影响它对数据的正确使用和修改
  • 持续性:一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对其执行结果有任何影响

# 数据库恢复概述 (了解)

故障是不可避免的

  • 计算机硬件故障
  • 系统软件和应用软件的错误
  • 操作员的事务
  • 恶意的破坏

故障的影响:

  • 运行事务非正常中断
  • 破坏数据库

数据库管理系统对故障的对策:

  • DBMS 提供恢复子系统
  • 保证故障发生后,能把数据库中的数据从错误状态恢复到某种逻辑一致的状态
  • 保证事务 ACID

# 故障的种类

# 一、事务故障

事务故障:某个事务由于种种原因未运行至正常终点就夭折了

事务故障常见原因:

  • 输入数据有误
  • 运算溢出
  • 违反了某些完整性限制
  • 某些应用程序出错
  • 并行事务发生死锁

事务故障恢复

  • 对于可以预见的错误,由事务程序来处理
  • 对于不可预见的错误,有 DBMS 强行回滚该事务

# 二、系统故障

系统故障:

  • 整个系统的正常运行突然被破坏
  • 所有正在运行的事务都非正常终止

系统故障常见原因:

  • 操作系统或 DBMS 代码错误
  • 操作员操作失误
  • 特定类型的硬件错误 (如 CPU 故障)
  • 突然断电

系统故障的恢复:

  • 清除尚未完成的事务对数据库的所有修改
  • 将缓冲区中已完成的事务提交的结果写入数据库

# 三、介质故障

介质故障:

介质故障是指存储数据的设备 (如硬盘) 发生故障,使存储在其上的数据部分丢失或全部丢失

介质故障产生原因:

  • 磁盘损坏
  • 操作系统的某种潜在原因
  • 瞬时磁场干扰

介质故障的恢复:

  • 装入数据库发生介质故障前某个时刻的数据副本
  • 重做自此时始的所有成功事务,将这些事务已提交的结果重新记入数据库

# 恢复的实现技术

数据是不可再生资源。必须保证数据不丢失,在发生各类故障,数据被破坏时能够及时恢复

恢复操作的基本原理是冗余,即利用存储在系统其他地方的冗余数据来重建数据库中已被破坏或不正确的那部分数据。

恢复机制涉及的关键问题:

  • 如何建立冗余数据
    • 数据转储
    • 登录日志文件
  • 如何利用这些冗余数据实施数据库恢复

# 数据转储

# 一、什么是转储

转储是指 DBA 将整个数据库复制到磁带或另一个磁盘上保存起来的过程。这些备用的数据文本称为后备副本或后援副本

# 二、转储的分类
# 1、静态转储
  • 在系统中无运行事务时进行转储
  • 转储开始时数据库处于一致性状态
  • 转储期间不允许对数据库的任何存取、修改活动
  • 优点:实现简单
  • 缺点:降低了数据库的可用性
    • 转储必须等用户事务结束
    • 新的事务必须等待转储结束
# 2、动态转储
  • 转储操作与用户事务并发进行
  • 转储期间允许对数据库进行存取或修改
  • 优点:
    • 不用等待正在运行的用户事务结束
    • 不会影响新事物的运行
  • 动态转储的特点
    • 不能保证副本中的数据正确有效
# 3、海量转储:每次转储全部数据库
# 4、增量转储:只转储上次转储后更新过的数据

转储策略:应定期进行数据转储,制作后备副本

# 登记日志文件

什么是日志文件:

日志文件 (log) 是用来记录事务对数据库的更新操作的文件

日志文件的格式及内容

  • 以记录为单位的日志文件
    • 各个事务的开始标记 (BEGIN TRANSACTION)
    • 各个事务的结束标记 (END TRANSACTION)
    • 各个事务的所有更新操作
    • 事务有关的内部更新操作
  • 以数据块为单位的日志文件
    • 事务标识
    • 操作类型 (插入、删除或修改)
    • 操作对象 (记录 ID,Block NO.)
    • 更新前数据的旧值 (对插入操作而言,此项为空)
    • 更新后数据的新值 (对删除操作而言,此项为空)

日志文件的用途:

  • 进行事务故障恢复
  • 进行系统故障恢复
  • 介质故障恢复 (协助后备副本进行)

登记日志文件的原则:

  • 登记的次序严格按并行事务执行的时间次序
  • 必须先写日志文件,后写数据库
    • 写日志文件操作:把表示这个修改的日志记录写到日志文件
    • 写数据库操作:把对数据的修改写到数据库中
  • 为什么要先写日志文件:
    • 如果先写了数据库修改,而日志文件中没有登记下这个修改,则以后无法恢复这个修改了
    • 如果先写日志,但没有修改数据库,按日志文件恢复时只不过多执行一次不必要的 UNDO 操作,并不会影响数据库的正确性

# 恢复策略

# 事务故障的恢复

恢复方法:由恢复子系统应利用日志文件撤销 (UNDO) 此事务已对数据库进行的修改

事务故障的恢复由系统自动完成,对用户是透明的,不需要用户干预

事务故障的恢复步骤:

  • 反向扫描日志文件 (即从最后向前扫描日志文件),查找该事务的更新操作
  • 对该事务的更新操作执行逆操作。即将日志记录中 "更新前的值" 写入数据库
    • 插入操作:相当于删除操作
    • 删除操作:相当于插入操作
    • 修改操作:用修改前的值代替修改后的值
  • 继续反向扫描日志文件,查找该事务的其他更新操作,并做同样处理
  • 如此处理下去,直到读到此事务的开始标记,事务故障恢复就完成了

# 系统故障的恢复

系统故障造成数据库不一致状态的原因

  • 未完成事务对数据库的更新已写入数据库
  • 已提交事务对数据库的更新还留在缓冲区还没来得及写入数据库

恢复方法:

  • UNDO 故障发生时未完成的事物
  • Redo 已完成的事物

系统故障的恢复由系统在重新启动时自动完成,不需要用户干预

系统故障恢复步骤:

  • 正向扫描日志文件 (即从头扫描日志文件)
    • 重做 (REDO) 队列:在故障发生前已经提交的事务
    • 撤销 (Undo) 队列:故障发生时尚未完成的事务
  • 对撤销 (Undo) 队列事务进行撤销 (Undo) 处理
    • 反向扫描日志文件,对每个 UNDO 事务的更新操作执行逆操作
    • 即将日志记录中 "更新前的值" 写入数据库
  • 对重做 (Redo) 队列事务进行重做 (Redo) 处理
    • 正向扫描日志文件,对每个 Redo 事务重新执行登记的操作
    • 即将日志记录中 "更新后的值" 写入数据库

# 介质故障的恢复

  • 重装数据库
  • 重做已完成的事务

恢复步骤:

  • 装入最新的后备数据库副本 (离故障发生时刻最近的转储副本),使数据库恢复到最近一次转储时的一致性

    • 对于静态转储的数据库副本,装入后数据库即处于一致性状态
    • 对于动态转储的数据库副本,还须同时装入转储时刻的日志文件副本,利用与恢复系统故障的方法 (即 REDO+UNDO),才能将数据库恢复到一致性状态
  • 装入有关的日志文件副本 (转储结束时刻的日志文件副本),重做已完成的事物

    • 首先扫描日志文件,找出故障发生时已提交的事务的标识,将其记入重做队列
    • 然后正向扫描日志文件,对重做队列中的所有进行事务进行重做处理。即将日志记录中,"更新后的值" 写入数据库
  • 介质故障的恢复需要 DBA 介入

  • DBA 的工作

    • 重装最近转储的数据库副本和有关的各日志文件副本
    • 执行系统提供的恢复命令
  • 具体的恢复操作仍由 DBMS 完成

# 具有检查点的恢复技术

两个问题

  • 搜索整个日志文件将耗费大量的时间
  • REDO 处理:重新执行,浪费了大量时间

具有检查点的恢复技术:

  • 在日志文件中增加检查点记录
  • 增加重新开始文件
  • 恢复子系统在登录日志文件期间动态地维护日志

检查点记录的内容:

  • 建立检查点时刻所有正在执行的事务清单
  • 这些事务最近一个日志记录的地址

重新开始文件的内容:

  • 记录各个检查点记录在日志文件中的地址

动态维护日志文件的方法:

  • 周期性地执行如下操作:建立检查点,保存数据库状态

具体步骤是:

  • 将当前日志缓冲区中的所有日志记录写入磁盘的日志文件上
  • 在日志文件中写入一个检查点记录
  • 将当前数据缓冲区的所有数据记录写入磁盘的数据库当中
  • 把检查点记录在日志文件中的地址写入一个重新开始文件

恢复子系统可以定期或不定期地建立检查点,保存数据库状态

  • 定期:按照预定的一个时间间隔,如每隔一个小时建立一个检查点
  • 不定期:按照某种规则,如日志文件已写满一般建立一个检查点

使用检查点方法可以改善恢复效率

  • 当事务 T 在一个检查点之前提交,T 对数据库所做的修改已写入数据库
  • 写入时间是在这个检查点建立之前或在这个检查点建立之时
  • 在进行恢复处理时,没必要对事务 T 执行 REDO 操作

利用检查点的恢复步骤:

  • 从重新开始文件中找到最后一个检查点记录在日志文件中的地址,由该地址在日志文件中找到最后一个检查点记录
  • 由该检查点记录得到检查点建立时刻所有正在执行的事物清单 ACTIVE-LIST
    • 建立两个事务队列
      • UNDO-LIST
      • REDO-LIST
    • 把 ACTIVE-LIST 暂时放入 UNDO-LIST 队列,REDO 队列暂时为空
  • 从检查点开始正向扫描日志文件,直到日志文件结束
    • 如有新开始的事务 T,把 T 暂时放入 UNDO-LIST 队列
    • 如有提交的视图 T,把 T 从 UNDO-LIST 队列中移到 REDO-LIST 队列
  • 对 UNDO-LIST 中每个事务执行 UNDO 操作,对 REDO-LIST 中每个事务执行 REDO 操作

# 数据库镜像

介质故障是对系统影响最为严重的一种故障,严重影响数据库的可用性

  • 介质故障恢复比较费时
  • 为预防介质故障,DBA 必须周期性地转储数据库

提高数据库可用性的解决方案:数据库镜像

数据库镜像:

  • DBMS 自动把整个数据库或其中的关键数据复制到另一个磁盘上
  • DBMS 自动保证镜像数据与主数据库的一致性,每当主数据库更新时,DBMS 自动把更新后的数据复制过去

出现介质故障时:

  • 可由镜像磁盘继续提供使用
  • 同时 DBMS 自动利用镜像磁盘数据进行数据库的恢复
  • 不需要关闭系统和重装数据库副本

频繁地复制数据自然会降低系统运行效率

  • 在实际应用中用户往往只选择对关键数据和日志文件镜像,而不是对整个数据库进行镜像