码迷,mamicode.com
首页 > 数据库 > 详细

数据库复习7——恢复

时间:2015-06-28 23:08:28      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:数据库   恢复   基于日志的恢复   事务   

数据库复习


CH14 恢复

13.1 恢复的概念

数据库系统中恢复是指让数据库从发生某些“失败”后的不一致的状态恢复到正常的一致状态的行为,恢复的基础是冗余(物理上冗余,非逻辑上)

这些失败包括了:

  • 事务失败:包括逻辑错误(事务不满足某些条件不能执行)和系统错误(DBMS强制终止事务,如事务发生死锁)
  • 系统崩溃:断电、物理硬件损坏、软件系统(如OS)崩溃,本章假设系统崩溃不会改变非易失存储器
  • 磁盘失败:磁盘存储发生错误,本章假设可利用检查和监测磁盘失败

大体上,恢复策略分成两个步骤:

  • 正常事务处理时,记录足够的额外信息以供失败时恢复
  • 失败发生后,讲数据库返回一致性状态的动作

13.2 存储结构和数据访问

本小节假设讨论恢复问题时的存储结构和数据访问模型

按系统奔溃时是否影响数据存储,将存储器分成易失存储器(主存、cache等)和非易失存储器(磁盘磁带、闪存、非易失RAM等),然后我们假设一种理想的稳定存储器(stable storage),发生任何失败时都不会影响存储数据内容

定义物理块为存储在非易失的磁盘上的块,缓冲块是为存储在易失的主存中的块,而私有空间是指为每个事务T分配的独立于其他事务的虚拟存储区域,那么可以命名一下4种操作:

  • input(A):从磁盘中加载物理块到主存
  • output(A):把主存中缓冲块写回磁盘
  • read(X):从主存中将缓冲块读取到私有空间
  • write(X):把私有空间中的本地副本写回到主存

假设在事务中,DBMS在第一次访问块X时调用一次read操作加载到私有缓冲区,事务执行完毕时write(X)写回主存,而事务中间的操作时都只是修改其本地副本

注意,DBMS没有必要在每次write时调用output,这取决于OS的写回策略

13.3 基于日志的恢复

日志是一组记录在理想的稳定存储器上的数据库存储记录,约定:

  • 事务Ti开始时,日志记录<Ti, start>
  • 事务Ti执行write操作时,日志记录<Ti, X, old_value, new_value>
  • 事务Ti结束时,日志记录<Ti, commit>
  • 任何时候最多只有一个事务活跃

基于日志的恢复有两种策略,推迟数据库修改立即数据库修改

(1)推迟数据库修改

推迟数据库修改模式下,数据库的修改操作仅记录在Log中而不真正的实施write操作,直到partial committed之后才write

定义在失败发生时的redo和undo操作:

  • redo:按照Log中的<Ti, X, old_value, new_value>再一次写入新值new_value
  • undo:按照Log中的<Ti, X, old_value, new_value>撤销新值写入,即写入old_value

由推迟数据库修改模式的定义知,未记录<Ti, commit>的事务不执行任何恢复操作,已记录<Ti, commit>的事务顺序地执行redo操作(其实这种模式下old_value是没有必要记录的)

(2)立即数据库修改

立即数据库修改模式和推迟数据库修改模式相反,事务未commit之前就允许修改数据库,write-ahead logging rule(WAL规则)规定log记录必须在数据库写入之前完成

立即数据库修改下,未记录<Ti, commit>的事务必须反序地执行undo操作让数据库返回到一致性状态,而已记录<Ti, commit>的事务顺序地执行redo操作

(3)检查点

每次redo和undo时都遍历整个Log并完成所有事务的redo和undo的话,开销十分巨大,并且对于已经commit后output写入磁盘的redo是没有任何意义的,因此在Log引入<checkpoint>语句

DBMS周期性地做检查工作,把所有commit的事务(已write入主存)从主存中写回到磁盘中,并在日志中记录一条<checkpoint>;注意检查时,可能某个事务还未commit

有了检查点的数据库恢复,每次错误时只需恢复最近的事务即可:

  1. 反向遍历日志,直到找到第一个<checkpoint>
  2. 继续反向遍历,找到最近一个未commit的事务起点<Ti, start>
  3. 从该句开始执行响应的redo和undo操作

那么对于下面的时序图,发生失败时有(立即数据库修改模式):

技术分享

  • T1被忽略
  • redo T2和T3
  • undo T4

13.4 影子数据库

除了基于日志的恢复,还另一种恢复策略——影子数据库(Shadow Database),它有以下设定

  • 假设任何时候只有一个事务活跃
  • db_pointer指针总是指向数据库当前的一致性副本
  • 所有的update都是在数据库的影子拷贝(shadow copy)上完成的,只有当事务partial committed之后才把影子拷贝中的副本写入磁盘中,并且更新db_pointer
  • 事务失败时转向db_pointer指向的一致性的数据库,当前影子数据库被直接删除
  • 假设磁盘不会失败

影子数据库的拷贝策略运用在大型数据库上十分低效

13.5 并发事务的恢复

13.3中介绍的基于Log的恢复是针对单活跃事务而言的,下面进行更多的假设已完成对并发事务的恢复

  • 所有的事务共享一份存储缓冲和一份日志记录
  • 一个缓冲块中可以有多个事务修改后的数据
  • 并发控制严格遵循两阶段锁(下一章详细描述),保证未commit的事务间不可见
  • 并发事务的Log可以交织在一起
  • 检查点发生时,可能有多个事务正处在活跃状态,记录<checkpoint, L>,L是检查点发生时活跃的事务列表
  • 当失败发生时执行一下动作:初始化undo_listredo_list为空表,倒序找到第一个<checkpoint, L>,对于L中每一个事务的update按Log记录反序加入undo_list、正序加入redo_list
  • 执行undo_listredo_list中的操作

13.6 缓存管理

(1)Log记录缓存

如果把Log缓存在主存中,那么当缓存已满log force操作时才把Log记录(全部)写入磁盘(这样多条log记录可以一次output,减少I/O开销),此外Log记录缓存还必须遵从以下约定:

  • log记录必须顺序地output进磁盘
  • 事务Ti只有当<Ti, commit>写入磁盘后才能进入Committed状态
  • log记录必须比相应修改后的数据先写入磁盘

(2)数据库缓存

数据库缓存和Log记录缓存不一样的是,它是分块划分缓存的,当缓存满时是选择缓存块被新块替换(若修改需要写回磁盘),而不整个缓存写回

13.7 非易失存储器的失败

上述对恢复的讨论仅包含易失存储器的部分,非易失存储器的恢复也利用了相似的分层存储器思想:增加一种dump操作,它下一级是理想的稳定存储器(可以假想为磁带等层次更低的存储介质)

数据库复习7——恢复

标签:数据库   恢复   基于日志的恢复   事务   

原文地址:http://blog.csdn.net/u014030117/article/details/46674469

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!