3-3:恢复系统

磁盘故障/电源故障/软件错误/人为破坏/...
即使发生故障,也能保证原子性,持久性.
恢复机制用于将数据库在遭遇故障时,将其恢复到故障发生前的一致性状态

故障分类

- 事务故障
事务逻辑错误
系统错误[如死锁]
- 系统崩溃
硬件错误/软件漏洞
- 磁盘故障

故障发生后仍保证数据库一致性/事务原子性的算法,称为恢复算法.
1.有足够信息用于故障恢复
2.利用信息进行恢复

存储器

- 易失性存储器
- 非易失性存储器
- 稳定存储器

稳定存储器的实现

在多个非易失性存储介质上以独立的故障模式复制信息
以受控的方式更新信息
以保证数据传送过程中发生的故障不破坏所需信息

磁盘镜像
远程备份

在内存和磁盘存储器间进行块传送有以下几种可能结果:
- 成功完成
- 部分失败
- 完全失败

要求,
如数据传送故障发生,
系统能检测到且调用恢复过程将块恢复为一致的状态
系统需为每个逻辑数据库块维护两个物理块
输出:
1.将信息写入第一个物理块
2.将信息再写入第二个物理块

恢复:
对每一个块
检查其关联的两个物理块.如两者相同,且块内自检通过.则略过.
如块内自检有错,用另一无错块内容写入有错块.
如块内自检都通过,但内容不一致,采用一个覆盖另一个.让其内容一致.

上述方法可保证写操作,
要么完全成功,要么完全失败

数据访问

设没有数据项跨越多个块
内存-磁盘以磁盘块为单位进行数据交换.
位于磁盘上的块称为物理块,
临时位于主存的块称为缓冲块.
内存中用于临时存放块的区域称为磁盘缓冲区.
- input(B)
将物理块B送至内存
- output(B)
将缓冲块B送至磁盘,并替换磁盘上相应的物理块


每个事务有一个私有工作区,
用于保持事务访问和更新的数据项的拷贝
事务提交/终止时,删除.
1.read(x)
若x不在主存,执行input(B_{x}),将包含x的块读入主存
若在主存,取x
2.write(x)
若x不在主存,执行input(B_{x}),将包含x的块读入主存
若在主存,写x

如数据库系统发指令执行output(B_{x}),称对缓冲块B执行强制输出.
提交的事务所做的更新,即使发生故障.
更新也不会丢失.

恢复与原子性

修改数据库本身前,
先向稳定存储器输出信息,描述要做的修改
输出的信息能帮助我们
1.确保已提交事务做的所有修改都反映到数据库中
故障时,利用这些信息进行故障恢复来生效
事务中止时,利用这些信息撤销已经对数据库做的部分修改.

日志记录

日志记录,它记录数据库中的所有更新活动
- 更新日志记录[日志记录的一种类型]
描述一次数据库写操作
有如下几个字段:
1.事务标识
执行该操作的事务
2.数据项标识
标识数据项,通常用数据项所在磁盘块,块内偏移表示
3.旧值
更新前的值
4.新值
- 事务开始日志记录
表示事务的开始
- 事务提交日志记录
表示事务的提交
- 事务中止日志记录
表示事务的中止

事务执行写操作时,
先建立该操作的日志记录,将记录写入日志
再实际执行写数据库.

日志记录让我们有能力进行操作的撤销/重做.
日志需放在稳定存储器中.

数据库修改

事务在对数据库进行修改前,先创建日志记录,写入日志.
在事务中止下,利用其之前产生的日志,可对其已经做出的各项修改进行撤销.
在事务已经提交,但修改尚未写入磁盘上数据库之间崩溃下.可对其已经做出的各项修改进行重做.

事务执行数据项修改的步骤:
1.在主存事务私有部分执行计算
2.对磁盘缓冲区中含对应数据项的块进行修改
3.执行output,将磁盘缓冲区内的数据块写到磁盘
如事务对磁盘缓冲区内的块或磁盘自身进行了更新,则称其修改了数据库.
如仅在主存中对事务私有部分进行修改,则不算对数据库的修改.
事务提交时,若仍然没修改数据库,称其采用了延迟修改技术.
这种情况下,
事务对修改的数据项,先拷贝一份到事务私有部分.
之后指向和修改其私有部分.
事务执行中,即修改了数据块,称其采用了立即修改技术.

有可能事务已经提交,但其修改仍然在磁盘缓冲区,而非磁盘上数据库中.
有可能一个事务已经修改了数据库,但执行了某一步需要中止.
- undo
使用一个日志记录,将指明的数据项设为旧值
- redo
使用一个日志记录,将指明的数据项设为新值

并发控制和恢复

一般,数据项X被事务A修改了,
则在A提交或中止前,不允许其他事务修改X.
[对更新数据项X申请排他锁,事务提交时才释放锁]

事务提交

一个事务的commit日志记录为其最后一个日志记录,写入日志后.就称事务提交了.
此后,即使系统崩溃,事务所做的更新也可重做.
如在事务的commit日志记录输出到稳定存储器前,崩溃.
事务回滚.

包含commit日志记录的块的输出,导致了事务的提交.
事务提交时事务修改的缓冲区块,可以立即写入文档存储器,也可后续写入.

使用日志来重做和撤销事务

- redo(T)
将事务T更新过的所有数据项的值都设为新值
扫描日志,对扫描范围的每个日志记录逐个处理
- undo(T)
将事务T更新过的所有数据项的值都设为旧值
撤销过程也产生日志记录[redo-only日志记录]
对事务T的undo操作完成后,写一个<T abort>日志记录,表示撤销完成.

每个事务在日志中,最终要么有一个commit,要么有一个abort.
发生系统崩溃后,查阅日志
- 对T
1.如日志中含<T start>
但既不含<T commit>又不含<T abort>
则需对T执行撤销
2.如日志中含<T start>
及<T commit>或<T abort>
需对T进行重做.
如在日志中有<T abort>
意味着日志中有undo操作所产生的redo-only日志记录.对其重做意味着对T的撤销.

在这里插入图片描述

	若崩溃重启后,日志如a所示,
	则对T_{0}执行撤销,撤销后A为1000, B为2000
	若崩溃重启后,日志如b所示,
	则对T_{1}执行撤销,对T_{0}执行重做.处理后A为950,B为2050,C为700
	若崩溃重启后,日志如c所示,
	则对T_{0},T_{1}执行重做,处理后A为950,B为2050,C为600

检查点

系统故障时,若针对日志整体依次对所有出现的事务执行
重做或撤销.则,耗时严重.

- 检查点具体执行过程
1.将当前位于主存的所有日志记录输出到稳定存储器
2.将所有修改的缓冲块输出到磁盘
3.将一个日志记录<checkpoint L>输出到文档存储器.
L是执行检查点时正活跃的事务的列表.

检查点执行过程,不允许事务执行任何更新动作,如往缓冲块写入,写日志记录等.
若某事务A的<A commit>记录在日志中位于<checkpoint L>记录前,
则恢复时,不必再对A的相关日志记录进行redo.

系统崩溃后,
系统检查日志,以找到最后一条<checkpoint L>记录
只需对L中的事务,及<checkpoint L>记录写到日志中后才开始的事务执行undo或redo.
把此事务集合即为T
对T中任一事务设为A
1.若日志中无<A commit>和<A abort>
则执行undo(A)
2.若日志中有<A commit>或<A abort>
则执行redo(A)

总以,
一旦检查点完成了,
就不再需要L对应事务集合关联的
<X start>集合中在日志中最先出现的那个<P start>之前的所有日志记录,
对后续恢复不再有意义,可以从日志文件删除掉这部分日志记录.

恢复算法

使用日志记录从事务故障中恢复的完整恢复算法
将最近的检查点和日志记录集合起来从系统崩溃中进行恢复的算法

事务回滚

- 正常操作时的事务T的回滚
1.从后往前扫描日志
对发现的每个形如<T, X, V_{1}, V_{2}>的日志记录
a.值V_{1}被写到数据项X
b.往日志中写一个特殊的日志记录<T, X, V_{1}>
这样的日志记录只会在崩溃恢复时被执行redo,不会被执行undo
2.一旦发现<T start>日志记录
就停止从后往前扫描
并往日志中写一个<T abort>

这样对事务T
该事务所做的,和对其撤销所做的每个动作都记录到了日志.

- 系统崩溃后的恢复
崩溃发生后当数据库系统重启时,恢复动作分两阶段进行
1.在重做阶段
系统从最后一个检查点日志记录处开始正向扫描日志来重做所有每个扫描到日志记录所做操作.
这些被重做的事务包含崩溃前已经回滚的事务,崩溃时尚未提交的事务.
扫描过程采取的步骤如下:
a.将要回滚的事务列表undo-list初始设定为<checkpoint L>日志记录中的L列表
b.一旦遇到形如<T, X, V_{1}, V_{2}>的正常日志记录或形如<T, X, V_{2}>的redo-only日志记录,就对其执行重做.即为将X设为V_{2}.
c.一旦遇到形如<T start>的日志记录
就把T加到undo-list
d.一旦遇到形如<T abort>或<T commit>的日志记录,就把T从undo-list中去掉.

redo阶段在扫描并处理完崩溃发生时日志中的最后一个日志记录后结束.
此时undo-list包括在崩溃前尚未完成的所有事务.

2.在撤销阶段
系统回滚undo-list中的所有事务
从日志尾端开始反向扫描日志来执行回滚
a.对扫描到的日志记录,若该记录关联的事务在undo-list中,就对其执行undo.
且执行undo后产生一条<T,X,V>形式的日志记录,写入日志末尾.
b.系统发现undo-list中事务T的<T start>日志记录时,
就从undo-list中删除T,且产生一条<T abort>形式的日志记录,写入日志末尾.
c.一旦undo-list变为空表,撤销阶段结束.


撤销阶段结束后,即可开始正常的事务处理.

在这里插入图片描述

缓冲区管理

日志记录缓冲

将一个块输出到稳定存储器的开销非常高,最好是一次输出多个日志记录.
将日志记录写到主存的日志缓冲区.
稳定存储器中的日志记录顺序需与写入日志缓冲区的顺序一样.

先写日志规则:
1.在日志记录<T commit>输出到稳定存储器后,事务T进入提交状态
2.在日志记录<T commit>输出到稳定存储器前,与T有关的所有日志记录需已经输出到稳定存储器
3.在主存中的数据块输出到数据库[稳定存储器]前,所有与该数据块中数据有关的日志记录需已经输出到稳定存储器.

将缓冲的日志写到磁盘有时称强制日志
此机制可用来保证事务原子性

数据库缓冲

- 强制策略
事务提交时,强制地将修改过的所有块都输出到磁盘
- 非强制策略
提交状态后,一段时间事务修改的某些块仍然未写回磁盘
非强制策略下不影响正确性[因为日志已经写入]
但有助于减少和磁盘块输出次数,也利于事务较快提交.

- 非窃取策略
一个活跃的事务修改过的块不应写出到磁盘
- 窃取策略
允许将活跃事务修改过的块写出到磁盘
窃取下不影响正确性[因为日志已经写入]
但有助于避免较多已更新块占据缓冲区,影响空间使用效率.

要将块B输出到磁盘时,
所有与块B中的数据相关的日志记录需在块B输出前先输出到稳定存储器.
块B输出中,不能往块B进行写.
1.事务对一个数据项执行写前,获得数据项所在块的排他锁
更新执行完释放该锁
2.一个块要输出时,
2.1.获取该块上的排他锁,保证无事务对该块写
2.2.将该块相关的所有日志记录保证输出到稳定存储器
2.3.将块输出到磁盘
2.4.块输出完成,释放锁

缓冲块上的锁还可用来保证在检查点进行过程中缓冲块不更新,且没新的日志记录产生
1.检查点操作开始前获得在所有缓冲块上的排他锁
及对日志的排他锁
2.检查点操作完成可释放锁

操作系统在缓冲区管理中的作用

管理数据库缓冲区可选方法
1.数据库系统保留部分主存作缓冲区,对其管理,不让操作系统管理.
缺点是限定了一块内存区域为数据库专用[类似通道静态划分].
2.数据库系统在操作系统提供的虚拟内存中实现其缓冲区.
操作系统决定哪个缓冲块何时强制输出到磁盘.
但对对数据库缓冲页,应由数据库系统强制输出缓冲块.
遗憾的是,一般操作系统完全控制虚拟内存-内存间交互.
操作系统保留的以存储当前不在主存的那些虚拟页的磁盘空间称为交换区.
如操作系统输出一个块,该块会输出到磁盘交换区.数据库系统无法控制此过程.

数据库文件和虚拟内存缓冲区间的数据传送需由数据库系统管理.
操作系统控制的块从内存输出只会将块输出到磁盘交换区,不会输出到磁盘数据文件存储部分.
数据库系统需输出块B时,
此缓冲区块[虚拟内存块]当前在交换区
故操作系统先从交换区读入该块,可能还会从缓冲区换出一块到交换区以提供容纳空间
然后在由数据库系统控制该块内容输出到数据库[磁盘上非交换区部分.存储实际数据部分对应位置]

模糊检查点

允许在checkpoint记录写入日志后
在修改过的缓冲块写到磁盘前开始做更新.[只能更新和非本检查点过程要写入的块]

如写入checkpoint记录后,写完所有修改过缓冲块之前崩溃.
造成磁盘上不完全检查点.

一种处理方法:
将最后一个完全检查点记录在日志中的位置存在磁盘上固定位置.
所有修改过的缓冲块写完后,才更新它.

非易失性存储器数据丢失的故障

周期性将整个数据库的内容转储到稳定存储器中.
发生物理数据库块丢失时,
用最近转储的数据库复原.
在用日志完成转储时到故障间操作的恢复.

转储过程:
1.将当前位于主存的所有日志记录输出到稳定存储器中.
2.将所有缓冲块输出到磁盘.
3.将数据库内容拷贝到稳定存储器
4.将日志记录<dump>输出到稳定存储器

数据库内容的转储也称为归档转储.
将SQL DLL等语句写到文件转储用于后续重执行这些语句的方式叫SQL转储.

锁的提前释放和逻辑undo操作

逻辑操作

索引访问时,访问时获取索引页面锁,访问完毕即释放.即使关联事务还在执行.
操作执行前获得锁,执行完立即释放锁.
此后无法通过更新数据项旧值方式执行操作撤销[数据项的锁被操作释放后,会被其他事务中某操作获取,并修改数据项中与本事务不发生冲突部分].此时需执行一个补偿操作来撤销--逻辑undo操作.

逻辑undo日志记录

执行修改索引操作前
创建一<T, Q, operation-begin>日志记录
执行操作时,
按正常方式创建更新日志记录[物理日志]
操作结束,写一个形如<T, O, operation-end, U>[逻辑日志]日志记录
U表示undo信息.
如操作为往B+树插入一项
则undo的U指出要执行删除,指明删除基于的B+树,删除的项

逻辑操作要后续被执行时,执行前应保证数据库处于操作一致状态[对B+树,索引数据应处于某个操作已经结束状态.而非操作修改索引到一般又执行逻辑操作情况.]
幂等:一个操作执行多次与执行一次结果相同.

有逻辑undo的事务回滚

猜你喜欢

转载自blog.csdn.net/x13262608581/article/details/110352619
3-3