故障分类
事务故障
事物内部执行而产生的故障
- 运算溢出
- 死锁被选中撤销
- 违反完整性限制
恢复
- 事务回滚(撤销)
系统故障
软故障,指造成系统停止运转的任何时间,使得系统要重新启动
- 特定类型硬件错误
- 操作系统故障
- DBMS代码错误
- 系统断电
恢复
- 事务未提交:回滚(撤销)
- 事务已提交:重做
介质故障
硬故障,指外存故障
- 磁盘损坏
- 磁头碰撞
- 强磁场干扰
恢复
- 装入故障前的副本,并进行恢复
存储器分类
- 易失性存储器
- 非易失性存储器
- 稳定存储器
- RAID:在不同磁盘上为每个磁盘块保存两个拷贝
- 远程备份系统:本地一份拷贝,远程一份拷贝
数据转储
指DBA将整个数据库复制到磁带或另一个磁盘上保存起来,备用的数据成为后备副本或后援副本
静态转储
- 系统无运行事务时进行转储
- 转储开始时数据库处于一致性状态
- 转储期间不允许对数据库的任何存取、修改
- 得到的是数据一致性副本
优点
- 实现简单
缺点
- 必须等待正运行的用户事务结束
- 新事务必须等转储结束
动态转储
- 转储与用户事务并发进行
- 转储期间允许对数据库进行存取、修改
优点
- 不会等待正在运行的事务结束
- 不会影响新事务的运行
缺点
- 不能保证副本中数据正确有效
- 需要日志在后期恢复
海量转储
- 每次转储全部数据库
优点
- 恢复更方便
缺点
- 浪费空间
- 浪费时间
增量转储
- 只转储上次转储后更新过的数据
优点
- 更实用有效
缺点
- 数据不完整,需要使用恢复算法
数据库镜像
DBMS自动把整个数据库或关键数据复制到一个磁盘上
DBMS自动保证镜像数据与主数据库的一致性
作用
- 出现介质故障时
- 可由镜像磁盘继续提供使用
- 同时DBMS利用镜像磁盘进行恢复
- 没有出现故障
- 用于并发操作
优点
- 不需要关闭系统和重装数据库副本
缺点
- 频繁复制数据会减低系统运行效率,实际中只对关键数据和日志文件镜像
稳定存储器实现
要实现稳定存储器,需要在多个非易失性存储介质以独立的故障模式复制所需信息,并且以受控的方式更新信息,以保证数据传送过程中发生的故障不会破坏所需的信息
块传送结果
- 成功完成:传送的信息安全地到达目的地
- 部分失败:传送过程中发生故障,目标块有不正确的信息
- 完全失败:传送过程中故障发生得足够早,目标块完好无损
数据库维护两个物理块的输出过程
- 将信息写入第一个物理块
- 当第一个物理块成功写入时,将相同的信息写入第二个物理块
- 只有第二次写成功完成时,输出完成
恢复过程:检查两个拷贝
- 如果它们相同且没有检测到错误存在,则不需要采取进一步动作
- 如果检测到一个块有错误,用另一个块的内容替换这一块的内容
- 如果两个块都没检测错误,但内容不一致,用第一块的值替换第二块内容
数据库系统中的存储的块
输入输出操作以块为单位完成
- 物理块:磁盘上的块
- 缓冲块:临时位于主存的块
- 磁盘缓冲区:内存中用于存放临时块的区域
块移动引发的操作
- input(B):传送物理块B到主存
- output(B):传送缓冲块B到磁盘,替换磁盘上相应的物理块传送数据的操作
- read(X):将数据项X的值赋予局部变量x
- 若X所在的块Bx不在主存中,执行input(Bx)
- 将缓冲块Bx中X的值赋予x
- write(X):将局部变量x的值赋予缓冲块中的数据项X
- 若X所在块Bx不在主存中,执行input(Bx)
- 将x的值赋予缓冲块Bx中的X
日志
使用最广泛的数据库修改的结构
是日志记录的序列,记录数据库中所有更新活动
日志必须放在稳定存储器中
每次事务执行写操作时,必须在数据库修改前建立该次写操作的日志记录并把它们加到日志中
日志记录分类
- 更新日志记录
- 描述一次写操作
- 字段
- 事务标识
- 数据项标识
- 旧值
- 新值
- 表示为< Ti , Xj , V1 , V2 >
- 开始日志记录
- 表示为< Ti start>
- 提交日志记录
- 表示为< Ti commit>
- 中止日志记录
- 表示为< Ti abort>
- 检查点日志记录
- 表示为
数据库修改
步骤
- 事务在主存中自己私有的部分执行某些计算
- 事务修改主存的磁盘缓冲区中包含该数据项的数据块
- 数据库系统执行ouput操作,将数据块写到磁盘中
如果事务执行了对磁盘缓冲区或磁盘的更新,才算修改了数据库
修改策略
- 延迟修改
- 事务直到提交时都没有修改数据库
- 事务需要创建更新过的所有数据项的本地拷贝
- 如果一个事务读它更新过的数据项,必须从本地拷贝中读
- 恢复简单
- 立即修改
- 事务活跃时修改了数据库
并发控制
如果一个数据项被一个事务修改了,那么在该事务提交或中止前不允许其他事务修改该数据项
使用严格两阶段封锁
事务提交
当事务的commit日志记录输出到稳定存储器后,称事务提交了
如果系统崩溃发生在<
Ti
commit>输出到稳定存储器之前,事务
Ti
将会回滚
事务重做
redo(
Ti
):将事务Ti更新过的所有数据项的值设置为新值
- 如果日志包括<
Ti
start>记录,以及<
Ti
commit>或<
Ti
abort>记录,需要对事务
Ti
进行重做
- 对日志进行一次扫描,扫描过程中每遇到一个redo日志记录就执行redo动作
事务撤销
undo(
Ti
):将事务Ti更新过的所有数据项的值恢复成旧值
- 如果日志包括<
Ti
start>记录,但不包括<
Ti
commit>或<
Ti
abort>记录,需要对事务
Ti
进行撤销
- 写一个特殊的只读日志记录<
Ti
,
X
,
- undo完成后,写一个中止日志记录<
Ti
abort>
检查点
如果搜索整个日志进行重做和撤销
- 搜索太耗时
- 恢复过程太长
简单检查点
执行检查点操作过程中不允许执行任何更新
执行检查点的过程中将所有更新过的缓冲块都输出到磁盘
执行过程
- 将当前位于主存的所有日志记录输出到稳定存储器
- 将所有修改的缓冲块输出到磁盘
- 将一个日志记录
模糊检查点
允许在checkpoint记录写入日志后,但在修改过的缓冲块写到磁盘前开始做更新,但是正在输出到磁盘的缓冲块不能更新
将最后一个完全检查点记录在日志中的位置存在磁盘上的固定位置last_checkpoint上
执行过程
- 暂停所有事务
- 将一个日志记录
事务回滚
- 从后往前扫描日志,对所发现的 Ti 的每一个形如< Ti , Xj , V1 , V2 >的日志记录
- 值 V1 被写到数据项 Xj 中,并且
- 往日志中写一个只读日志记录< Ti , Xj , V1 >
- 一旦发现了< Ti start>日志记录,就停止从后往前的扫描,并往日志中写一个< Ti abort>日志记录
恢复算法
- 重做阶段:从最后一个检查点正向扫描日志重放所有事务的更新
- 将要回滚的事务列表undo-list初始设定为
缓冲区管理
日志记录缓冲
为了减少日志记录输出的开销,将日志记录写到主存的日志缓冲区,当日志缓冲区满或日志强制操作时,用一次输出操作输出到稳定存储器
先写日志规则(WAL)
- 在日志记录输出到稳定存储器后,事务Ti进入提交状态
- 在日志记录输出到稳定存储器前,与事务Ti有关的所有日志记录必须已经输出到稳定存储器
- 在主存中的数据块输出到数据库前,所有与该数据块中数据有关的日志记录必须已经输出到稳定存储器
数据库缓冲
- 强制策略:事务提交时强制地将修改过的所有的块都输出到磁盘
- 非强制策略(大多数系统采用):即使一个事务修改了某些还没有写回到磁盘的块,也允许它提交
- 非窃取策略:一个仍在活跃的事务修改过的块不应该写出到磁盘
- 窃取策略(大多数系统采用):允许系统将修改过的块写到磁盘,即使做这些修改的事务还没有全部提交
缓冲块中的闩锁
保证输出时没有正在进行的写
过程
- 获取该块的排他锁,以确保没有任何事务正在对该块执行写操作
- 将日志记录输出到稳定存储器,知道与块B相关的所有日志记录都输出了
- 将块B输出到磁盘
- 块B输出完成后,释放锁
缓冲块间循环输出
- 缓冲区中脏块减少
- 检查点过程中需要输出的块减少
- 当没有空闲的缓冲区,需要从缓冲区逐出一个块时,不脏的块可以被逐出,不需要等待输出完成
管理数据库缓冲区方法
- 数据库系统保留部分主存作为缓冲区
- 缺点
- 限制了主存使用的灵活性,缓冲区必须足够小,使其他应用有足够的主存
- 无法改变内存分区
- 数据库系统在操作系统提供的虚拟内存中实现缓冲区
- 缺点
- 操作系统完全控制虚拟内存。如果操作系统决定输出一个块B,块B就被输出到磁盘交换区,数据库系统无法控制缓冲块的输出
- 导致额外的磁盘输出。当需要输出到磁盘的块在磁盘交换区中,需要两次输出和一次输入