声明:本文配图和样本数据均来自《数据库系统概念》官网,再次对原作者表示感谢。
1 概述
1.1 数据库是如何访问数据的?
数据库系统常驻于非易失性存储器(主要是磁盘),在任何时间都只有部分内容在主存中。数据库分成称为块(block)的定长存储单位。块是磁盘数据传送的单位,可能包含多个数据项。事务由磁盘向主存输入信息,然后再将信息输出回磁盘。输入和输出操作都以块为单位。位于磁盘上的块为物理块,临时位于主存中的块称为缓冲块。内存中用于临时存放块的区域叫做磁盘缓冲区。
下面这张图描述了事务操作数据时的大致过程:
一般地,事务都有自己的私有工作区(事务初始化时创建),用于保存事务访问及更新的所有数据项的拷贝,在事务提交或者终止时删除。事务通过在其私有工作区和系统缓冲区之间传送数据(read(X)和write(X)),与数据库系统进行交互。
read(X)和write(X)操作都可能需要将块从磁盘传送到主存,但是它们都没有特别指明需要将块从主存传送回磁盘,也就意味着write(x)和output(B)并没有直接的对应关系,而是异步的,因为缓冲块B可能包含其它正在被访问的数据项。实际上,缓冲区的块写回磁盘一般发生于:1.缓冲区溢出需要交换内存空间;2.数据库系统希望将磁盘块B的变化反映到磁盘上。
事务对数据的完整更新操作应该包含3个部分:
- 在工作区完成对数据的计算处理。
- 调用write(X)将新数据更新到系统缓冲区。 --只要完成了这一步,就可以说事务修改了数据库。
- 数据据系统执行output(B)操作将缓冲块写回磁盘。
如果数据库系统在write(X)完成后和output(B)完成之前发生故障,事务已经提交的修改就会丢失。实际上,更大概率的事件是在事务提交之前就遇到了系统故障,而此时事务的部分更新已经写回磁盘,部分更新没有完成,破坏了磁盘数据的一致性。
因此,需要设计一些机制来保证数据据系统即使发生崩溃,事务的原子性也能得到保证,从而保证数据的一致性。
2 故障恢复的基础
在系统重启后,想要做一些恢复动作来保持原子性,就必须在修改数据库之前,先写入一些信息来记录后面的修改,这种工作也叫作预埋。使用最为广泛的记录数据库修改的结构就是日志,日志是日志记录的序列,它记录数据库中的所有更新活动。
2.1 日志记录
每次事务执行写操作时,必须在数据库修改前建立该次写操作的日志记录并把它加到日志中,而日志必须存放在稳定存储器中。这里需要注意的是,数据据系统所在的磁盘属于非易失性存储,也容易发生各种物理故障,比如磁头和扇区损坏。而日志所在的存储需要更高的稳定性,稳定存储器中的信息永远不会丢失(接近100%可靠),一般就是采用RAID技术来尽可能保证磁盘单点故障不会损坏到数据。
日志记录的结构:<,
, V_old, V_new>
它记录了某个事务在某个数据项上的修改,并保存了修改前的旧值和修改后的新值。通常是数据项在磁盘上的位置,