SQL Server事务日志-检查点、redo和undo(1)

日志记录

使用最为广泛的记录数据库修改的结构就是日志。日志是日志记录的序列,它记录数据库中的所有更新活动。
  日志记录有几种,更新日志记录(update log record)描述一次数据库写操作,它具有如下几个字段:

  • 事务标识:执行write操作的事务的唯一标识
  • 数据项标识:是所写数据项的唯一标识。通常是数据项在磁盘上的位置,包括数据项所驻留的块的块标识和块内偏移量
  • 旧值:数据项的写前值
  • 新值:数据项的写后值

我们将一个更新日志记录表示为,表明事务Ti对数据项Xj执行了一个写操作,写操作前Xj的值时V1,写操作后Xj的值是V2。其他专门的日志记录用于记录事务处理过程中的重要事件,如事务的开始以及事务的提交或中止。如下是一些日志记录类型:

  • :事务Ti开始
  • :事务Ti提交
  • :事务Ti中止

后面将介绍几种其他的日志记录类型。
  每次事务执行写操作时,必须在数据库修改前建立建立该次写操作的日志记录并把它加入到日志中。一旦日志记录已存在,就可以根据需要将修改输出到数据库中。并且,我们有能力撤销已经输出到数据库中的修改,这是利用日志记录中的旧值字段来做的。
  为了从系统故障和磁盘故障中恢复时能使用日志记录,日志必须存放在稳定存储器中。

数据库修改

事务在进行数据项修改中所采取的步骤:
  1.事务在主存中自己私有的部分执行某些计算。
  2.事务修改主存的磁盘缓冲区中包含该数据项的数据块。
  3.数据库系统执行output操作,将数据块写入磁盘中。

如果一个事务执行了对磁盘缓冲区或磁盘自身的更新,我们说这个事务修改了数据库;而对事务在主存中自己私有的部分进行的更新不算数据库修改。如果一个事务直到它提交时都没有修改数据库,我们就说它采用了延迟修改技术。如果数据库修改在事务仍然活跃时发生,我们就说它采用了立即修改技术

恢复算法必须考虑多种因素,包括:

  • 有可能一个事务已经提交了,虽然它所做的某些数据库修改还仅仅存在于主存的磁盘缓冲区中,而不再磁盘的数据库中。
  • 有可能处于活动状态的一个事务已经修改了数据库,而作为后来发生的故障的结果,这个事务需要终止。

由于所有的数据库修改之前必须建立日志记录,因此系统有数据库修改前的旧值和要写给数据项的新值可以用。这就使得系统能执行适当的undo和redo操作。

  • undo使用一个日志记录,将该日志记录中指明的数据项设置为旧值
  • redo使用一个日志记录,将该日志记录中指明的数据项设置为新值

检查点和日志的活动部分

当系统故障发生时,我们必须检查日志,决定哪些事务需要重做,哪些需要撤销。原则上,我们需要搜索整个日志来确定该信息。这样做有两个主要的困难:

  • 搜索过程太耗时
  • 根据我们的算法,大多数需要重做的事务已经把其更新写入数据库。尽管对它们重做不会造成不良后果,但会使恢复过程变得更长。

为了降低这种开销,引入检查点。

检查点操作
SQL Server 生成检查点的过程如下:

  • ①将标记检查点起点的日志记录写入日志文件。(日志记录≠日志文件)

  • ②将为检查点记录的信息存储在检查点日志记录链中。
      检查点中记录的一条信息是“最小恢复 LSN”(“MinLSN”),它是成功进行数据库范围内回滚所需的最早日志记录的日志序列号。MinLSN 是下列各项中的最小者:

  • 检查点起点的 LSN。

  • 最早的活动事务起点的 LSN。

  • 尚未传递给分发数据库的最早的复制事务起点的 LSN。

  • ③在检查点记录中记录所有的未完成的活动事务。

  • ④如果数据库工作在【简单恢复模式】,删除新的MinLSN之前的所有日志记录(日志截断)。

  • ⑤将当前位于主存的所有日志记录输出到稳定存储区。

  • ⑥将所有修改后的缓冲块写入磁盘。

  • ⑦将标记检查点记录结束的记录写入日志文件。

  • ⑧将检查点日志记录链输出到稳定存储器,其中L是执行检查点时正活跃的事务的列表。

在检查点执行过程中,不允许事务执行任何更新动作,如往缓冲块中写入或写日志记录。
  在上面的过程中,我们在日志中加入了记录使得系统提高恢复过程的效率。考虑在检查点前完成的事务Ti。对于这样的事务,记录(或记录)在日志中出现在记录之前。Ti所做的任何数据库修改都必然已在检查点前或作为检查点本身的一部分写入数据库。因此,在恢复时就不必再对Ti执行redo操作了。
  在系统崩溃发生之后,系统检查日志以找到最后一条记录(这可以通过从尾端开始反向搜索日志来进行,直到遇到第一条记录)
  只需要对L中的事务,以及记录写到日志中之后才执行的事务进行undo或redo操作。让我们把这个事务集合记为T。

  • 对T中所有事务Tk,若日志中既没有记录,也没有记录,则执行undo(Tk)。
  • 对T中所有事务Tk,若日志中有记录或记录,则执行redo(Tk)。

请注意,要找出事务集合T,和确定T中的每个事务是否有commit或abort记录出现在日志中,我们只需要检查日志中从最后一条checkpoint日志记录开始的部分。

MinLSN的选择
  MinLSN实际上代表了数据库从检查点恢复时,具体从哪个LSN号开始扫描并进行恢复。所以MinLSN的选择是检查点时的LSN和最早的活动事务起点LSN两者比较的最小值。
  如图,事务2为检查点时的唯一活动事务,其起点的LSN1小于检查点发生时的LSN2,所以MinLSN取LSN1就可以。

SQL Server事务日志-检查点、redo和undo(1)_第1张图片

检查点与恢复效率的关系
  检查点将脏数据页从当前数据库的缓冲区高速缓存刷新到磁盘上。 这最大限度地减少了恢复时必须重做(Redo)的修改量。
  为什么在日志文件中设置了检查点之后,基于日志的恢复机制就可以提高效率了呢?如图所示为检查点发生时可能的事务的状态。

SQL Server事务日志-检查点、redo和undo(1)_第2张图片

① 事务1
其start和commit日志记录都发生在检查点之前,这样的事务其结果已经反映到物理介质上去了(因为检查点会保证WAL协议,确保数据被写入),所以在恢复时无须对该事务做Redo操作。
② 事务2
其start日志记录在检查点之前发生,其commit记录在故障点之前发生,说明日志中事务已经完美提交,但数据不一定已经写入,所以属于圆满事务,需要Redo操作。
③ 事务3
其start日志记录在检查点之后发生,其commit记录在故障点之前发生,说明日志中事务已经完美提交,但数据不一定已经写入,所以属于圆满事务,需要Redo操作。
④ 事务4
其start日志记录在检查点之后发生,其commit记录在故障点之前尚未发生,说明日志中事务为中止事务,需要Undo操作。
⑤ 事务5
其start日志记录在检查点之前发生,其commit记录在故障点之前尚未发生,说明日志中事务为中止事务,需要Undo操作。

由CheckPoint的机制可以看出,由于内存中的数据往往比持久化存储中的数据更新,而CheckPoint保证了这部分数据能够被持久化到磁盘,因此CheckPoint之前的数据一定不会再需要被Redo。

自动检查点
   SQL Server 会自动产生检查点事件,它在后台有一条线程负责产生与执行检查点事件。 自动检查点之间的间隔基于使用的日志空间量以及自上一个检查点以来经历的时间。 如果只在数据库中进行了很少的修改,自动检查点之间的时间间隔可能变化很大并且很长。 如果修改了大量数据,自动检查点也会经常出现。
  自动检查点之间的间隔是以“恢复间隔”配置算出的。此选项指定数据库引擎在系统重新启动时恢复数据库所用的最长时间。 数据库引擎将估计在执行恢复操作期间自己在“恢复间隔”内能够处理多少条日志记录。
  自动检查点之间的间隔也取决于恢复模式:

  • 如果数据库使用的是完整恢复模式或批量日志恢复模式,则每当日志记录数达到数据库引擎估计在“恢复间隔”选项中指定的时间内可以处理的数量时,便会生成一个自动检查点。
  • 如果数据库使用的是简单恢复模式,只要日志记录数达到下面两个值中较小的那个值,就会生成自动检查点:
  • 日志已满 70%。
  • 日志记录数达到数据库引擎估计在“恢复间隔”选项指定的时间内能够处理的记录数。

你可能感兴趣的:(SQL Server事务日志-检查点、redo和undo(1))