聘我网

新概念招聘3.0

存储过程中是如何防止数据丢失的?

vote up0vote downstar

我看了一些开源项目的存储实现过程,

比如tokyocabinet

当提交时,其实它并没有直接将数据写入磁盘上

而是在之后的某个时刻批量写入

这个过程是怎么防止数据丢失的呢?

 

2 个答复

vote up0vote downcheck

一般都是通过WAL实现的

也就是在更改写入磁盘之前

确保描述更改的日志先被持久化

下面具体就IBM发明的ARIES技术来展开描述一些

共有3个阶段: 分析阶段、redo阶段和undo阶段

分析阶段

该阶段的目的是恢复系统崩溃之前的事务表和脏页面表。

过程是:

  1. 读取主记录,从而获取最后一次checkpoint动作的begin checkpoint记录的LSN,并在WAL中定位到该记录。
  2. 用前述begin checkpoint记录之后的end checkpoint记录中的数据初始化脏页面表和事务表。
  3. checkpoint动作开始之后的每条记录r:
    1. 如果r是某个事务Tend记录,则将T从事务表中移除,因为它已经完成。
    2. 如果r是事务T的非end记录,则确保T存在于事务表中。并且用r更新事务表:更新TlastLSN域,并且如果它已经开始commit,则记录下该事务的状态。
    3. 如果r是指向页面Pupdate或者CLR记录,确保P存在于脏页面表中。
    4. 到这里,我们已经获得了最新的事务表和脏页面表;它们将用于下一阶段。

注意这个阶段构造的脏页面表可能是非常保守的:

最后一次checkpoint动作之后WAL记录对页面的修改可能在系统崩溃前已经回填,

即它们可能实际并不脏。

但是由于我们能检测并避免已经执行的update,所以这不是个问题。

redo阶段

该阶段利用事务表和脏页面表,以及WALredo系统崩溃之前的所有更改。

该阶段过程是:

  1. 从脏页面表中找出最小的recLSN(代表可能还未回填的最老的WAL记录)
  2. 对于每个LSN大于或等于前述recLSN的记录r
    1. 如果r不是update或者CLR记录,忽略之。
    2. 如果r的目标页面不在脏页面表中,忽略之。
    3. 如果r的目标页面在脏页面表中,但该页面的recLSN大于rLSN,忽略之。
    4. 如果r的目标页面的page_LSN大于或等于rLSN,忽略之(该步需要获取页面的实际信息)。
    5. 否则,r应该被执行。从而,r的目标页面得到更改,且其page_LSN也被置为rLSN

注意这个阶段也会redo2种事务的更改:

  1. 系统崩溃前已经放弃的事务
  2. 事务在系统崩溃前仍处于in-progress状态(是被系统放弃而非主动放弃)。

前者的更改会被WAL中的CLR记录undo;后者的更改会在接下来的undo阶段undo

undo阶段

到达这个阶段,所有相关的记录已经被redo;系统的状态应该与崩溃之前完全一样。

最后要做的一件事是放弃所有系统崩溃前仍然active的事务,并且undo他们的更改。

过程如下:

  1. 此时事务表中的事务都是需要放弃的:称之为失败事务。每个事务的lastLSN域标记着该事务所做的最后一次更改的WAL记录。我们希望undo失败事务的更改,以与更改相反的顺序一路回退。故与其他阶段不同,该阶段从后往前读取WAL.
  2. 构建一张ToUndo表,初始值为所有失败事务的lastLSN。直到该表为空,重复以下步骤:
    1. ToUndo表移除最大的LSN项(即最后写入的WAL记录)。并获取对应的记录r
    2. 如果rupdate记录,则其更改需要undo。向WAL写入一条CLR之后便undo其更改。并将rprevLSN添加到ToUndo表。
    3. 如果rCLR记录,我们知道其所描述的undo动作已在redo阶段被redo。所以这里不需要再次undo。仅需要查看它的undoNextLSN域,如果是NULL,那就说明我们已经完成了该事务的undo,所以向WAL写入一条end记录之后便可将r扔掉。否则,将undoNextLSN添加到ToUndo表。

一旦ToUndo表为空,恢复工作便告完成。

如果该阶段再次发生系统崩溃

该阶段与前2个阶段不同,它会修改WAL,所以需要足够的健壮使得该阶段即使系统再次崩溃也不受影响。

  1. 我们知道系统的状态由WAL和磁盘数据共同构成。
  2. 该阶段通过undo失败事务的更改来修改磁盘数据。但是,在更改被undo之前,都会先写入描述该操作的CLR记录。如果系统在该阶段完成前再次崩溃,该CLR记录会在redo阶段再次被redo。从而保证了即使发生系统崩溃数据最终还是能够被修改。
  3. 该阶段向WAL写入CLR。但是,这不能避免系统崩溃。CLRundo的记录在WAL中位于CLR之前;因此,在redo阶段看到CLR时,其undo的记录已经被redo,从而CLR也能被redo。当在undo阶段遇到该CLR时,它的修改已经被redo —— 我们要做的只是把CLRundoNextLSN添加到ToUndo表。
链接
vote up0vote down

I'm impressed. You've really raiesd the bar with that.

链接

您的回答





不是您要找的问题? 浏览其他含有标签 的问题或者 自己问个.