写在前面
数据库事务恢复笔记。
问题
内容访问速度快但是容易崩溃不稳定。
磁盘稳定但是访问速度慢。
解决
将磁盘的数据页面读到内存缓冲区当中,以便计算机指令提供高速的随机访问。
一旦页面被读入内存的缓冲区,应该设法保存该页面以便不久之后的再次访问这样可以不用再访问磁盘,减少IO的开销。
后备缓冲
允许系统接收到一个磁盘的页面的请求的时候,先将其散列到后备表当中。如果在后备表当中有这一项说明对应的磁盘页面已经被读入缓冲区否则需要从磁盘读入该页。希望缓冲区保存的是最常使用的数据页面可以使用LRU缓冲策略。
LRU策略:读到内存当中的缓冲都被占满的时候一个新的读入的磁盘页面将会置换出最近最少使用的那个页面。
LRU缓冲模式是以减少磁盘的IO次数为目的的因此我们不能期望磁盘能和缓冲区的内容一致。
一个数据页面被称为是脏的:如果上一次写回磁盘之后被某些事物作了更新操作,我们通常会将脏的数据页面保留在内存当中直到更新该数据页面的事务被提交(或者按照LRU策略当该页面被其他页面置换出去的时候再写入磁盘)
但是一个数据页面长时间被操作但是在内存当中都没有被写入磁盘那么一旦断电或者内存崩溃内存上的信息将全部失去,如何保证能够恢复这些数据呢?如果采用每次更新就写回那么代价太大不可接受。
办法:日志
扫描二维码关注公众号,回复: 3037229 查看本文章
系统为每个更新操作做一个记录。称为日志项。
记录保存在称为日志缓冲区的内存区域。
日志项包含相应更新操作的足够的信息使得系统能够知道如何来重做该更新操作或者在事务中止的情况下撤销该更新的操作。
在合适的时刻日志缓冲区将被写回到磁盘上的一个称为日志文件的顺序文件当中。
该文件包含了过去某个时间段当中的所有的日志项。
一旦某一时刻内存当中的内容丢失,恢复进程就能够通过日志文件对磁盘的相应数据进行更新操作。
好处:
系统只需要以一个不太频繁的间隔进行日志缓冲区的写回操作节省IO操作。
磁盘写的双缓冲机制。
我的理解:每隔一段时间将日志缓冲区的内容写入磁盘
简单的模式当中:只有两种情况下我们才会将日志缓冲写回到日志文件当中。
- 当一些事物提交时
- 当日志缓冲区已满而没有多余的空间容纳更多的日志空间项时。
所以我们能够恢复的就是最后提交完成的那个事务和其之前的所有的事务。至于没有提交的但是有部分被写入磁盘的事务将撤回。所有提交的事务发出的更新都反应到了磁盘上所有未提交的事务发出的更新将都被回滚。
如何保证需要的日志都在磁盘上呢?
写回到磁盘的操作是原子操作意味着即使是在写磁盘的过程当中系统崩溃那么当下次读到写过的这块数据时,也能立即判断出写操作是否执行成功。没有不可检测的磁盘写错误是在系统崩溃时也是可以保证的。
将日志缓冲区写回到磁盘之前该事务不能认为是成功完成的。
系统保证相关的日志必须在相应的脏数据页面之前被写回到磁盘上。称之为先写日志原则。
检查点
希望记录系统启动之后经过一段合理的时间之后到达一个一致的状态。
这样恢复过程就不需要从日志最初的位置开始执行roll forward操作而只需要从记录这一点(检查点)开始操作即可。
三种创建数据库恢复检查点的不同的方法:
- 提交一致性检查点
- 高速缓存一致性检查点
- 模糊一致性检查点
介质恢复
一个磁盘上的数据也可能全部丢失,比如读写数据的磁头损坏就会导致这种问题。
这种情况需要特殊的恢复策略。
简单的介质恢复是这样的:
在系统启动之前,事务系统要用到的磁盘都做成批的拷贝。这些拷贝来自冗余的磁盘或者廉价的磁带介质,我们称之为数据的在线磁盘备份。当一个磁盘蹦了就用备份的磁盘来替换。
如果日志文件也损坏了怎么办?
我们需要遇见这一点并同时往两个不同的设备上写日志文件解决这个问题。这种技术成为日志镜像。我们的目的是通过保证两个镜像设备的独立存放日志来达到更高的可靠性。不同的供电系统不同的位置,存储的数据在两个设备上是一样的。这样的存储方案成为稳定的存储。