第23讲 数据库事务处理技术-故障恢复
数据库的故障类型及其影响
典型的数据库故障
事务故障
某一个程序(事务)自身运行错误所引起的故障
影响该程序(事务)本身系统故障
由于掉电、非正常关机等所引起的故障
影响正在运行的事务以及数据库缓冲区, 数据库缓冲区将涉及正在 运行和已经运行的事务介质故障
由于介质损坏等所引起的 故障
影响是全面的,既影响内存中的数据, 又影响介质 中存储的数据
数据库故障恢复的宏观思路
三种类型故障:事务故障、系统故障和介质故障
三种恢复手段: 事务的撤消与重做, 运行日志和备份
两个重要时刻:检查点和转储点
每个事务都会读写某些元素
READ(X,t):将元素X读到事务的局部变量t中;
WRITE(X,t):将事务局部变量t写回元素X;
INPUT(X):将元素X从磁盘读入到内存缓冲区中;
OUTPUT(X):将元素X写回到磁盘中。
每个事务都以提交或者撤销结束
COMMIT:事务提交
ABORT:事务撤销
DBMS在故障发生时需要保障事务
持久性
- 已提交的事务——缓冲区内容保证写回磁盘
- 未提交的事务——缓冲区内容不能影响磁盘
原子性
事务的所有操作,要么全都执行,要么全不执行。
注意:缓冲区内容和磁盘内容并不是时刻保持一致的。
不同缓冲区策略
Force:内存中的数据最晚在commit的时候写入磁盘。
No steal:不允许在事务commit之前把内存中的数据写入磁盘。
No force:内存中的数据可以一直保留,在commit之后过一段时间再写入磁盘。此时在系统崩溃的时候可能还没写入到磁盘,需要Redo,此方式较为灵活。
Steal:允许事务commit之前把内存中的数据写入磁盘,此时若系统在commit之前崩溃时,已经有数据写入到磁盘了,要恢复到崩溃前的状态,需要Undo,此方式同样较为灵活。
当前最常用:Steal + No force
什么是日志?
一个包含日志记录的、只能追加的顺序文件, 不同事务的日志记录交错存储,按发生时间存储。
发生系统故障时,使用日志进行恢复:
故障时已提交的事务,重做(Redo)
故障时未提交的事务,撤销(Undo)
Undo型日志及其故障恢复
对于任一事务T,按下列顺序向磁盘输出T的日志信息:
首先,<T, X, v>被写到日志中
其次,OUTPUT(X)
最后,
注意:Undo型日志仅保留旧值。<T, X, v>,v为X原来的值(X的旧值)
Undo型日志:“将事务改变的所有数据写到磁盘前不能提交该事务”
利用undo型日志进行恢复
首先,确定每一个事务是否已完成?
1 | <START T>….<COMMIT T>…. = yes |
检查点及其使用
静止检查点:
周期性地对日志设置检查点
停止接受新的事务, 等到所有当前活跃事务提交或终止,并在日志中 写入了COMMIT或ABORT记录后
将日志刷新到磁盘,写入日志记录,并再次刷新日志 非静止检查点
在设置检查点时不必关闭系统,允许新事务进入
写入一条<START CKPT(T1,…,Tk)>
其中T1,…,Tk 是所有活跃的未结束的事务
继续正常的操作,直到T1,…,Tk都完成时,写入
故障需恢复到所 遇到的第一个检查点
Redo型日志及其故障恢复
Redo型日志
Undo型日志的问题“将事务改变的所有数据写到磁盘前不能 提交该事务”—如何解决?
对于任一事务T,按下列顺序向磁盘输出T的日志信息:
1 | 首先,<T, X, v>被写到日志中 |
利用redo日志进行恢复
确定每一个事务是否已完成?
1 | <START T>….<COMMIT T>…. =yes |
从日志的起始位置开始按日志记录的正序处理每一日志记录,重做已提交事务的所有修改:
1 | <COMMIT T>: 标记T已完成 |
检查点
- 非静止检查点
在进行检查点设置时不必关闭系统,允许新事务进入
写入一条<START CKPT(T1,…,Tk)>
其中T1,…,Tk 是所有活跃的未结束的事务
将所有已提交的事务写回磁盘,
继续正常的操作,直到T1,…,Tk都完成时,写入
Undo/Redo结合型日志及其故障恢复
Redo型日志与Undo型日志的比较
Undo型日志:
OUTPUT必须先做。
如果
可见, T确定地已将所有其数据写回磁盘,因此不必重做 –– 但可能引起性能下降(因可能频繁地写磁盘)
Redo型日志:
OUTPUT必须后做。
如果
不可见, T确定地没有将其任何数据写回到磁盘, 因此无需撤销 –– 但灵活性差(数据必须在Commit后才可见)
如更喜欢灵活性 – 需要采用Undo/Redo型日志
Undo/Redo型日志
对于任一事务T,按下列顺序向磁盘输出T的日志信息:
1 | - 第(1)步,<T, X, u, v>被写到日志中 |
注意:与undo型和redo型的差别,在后两步。
Redo型是先写提交记录 后输出;
undo型是先输出,再写提交记录;
undo/redo型则无所谓谁先谁 后,只要保证<T,X,u,v>被先于OUTPUT写完即可。
利用undo/Redo型日志进行恢复
首先,确定每一个事务是否已完成?
1 | <START T>….<COMMIT T>…. = yes |
自前向后地,按日志记录的正序,重做所有已提交的事务;
自后向前,按日志记录的反序,撤销所有未完成事务的所有修改。
1 | <COMMIT T>: 标记T已完成 |
总而言之:自后向前地撤销所有未提交的事务;自前向后地重做所有已提交的事务;先做<撤销>,再做<重做>
转载无需注明来源,放弃所有权利