IT 论文精读 · PAPER 60

ARIES:数据库崩溃恢复

Mohan, Haderle, Lindsay, Pirahesh, Schwarz · IBM Almaden · ACM TODS 1992

EN →

这篇论文干了什么?

你点「确认转账」,屏幕回了「成功」。假如下一秒机房断电,这笔钱会不会扣了一半、另一半没到账?不会——这份底气很大程度上来自 1992 年 IBM 一队人发表的 ARIES:它把「崩溃之后怎么把账收拾干净」从各家各法的土办法,变成一套能讲清楚、能照着抄的标准做法。今天绝大多数数据库用的还是它的骨架。

先说说这有多难

数据库改数据不是改一笔落一笔盘——太慢。它先在内存里改,攒一攒才整块写回磁盘。于是断电那一瞬,磁盘上是一锅夹生饭:有的事务已经跟用户说了「成功」,改动却还在内存里(丢了);有的只做了一半、还没提交,弄脏的内存却被顺手刷了盘(脏了)。两种还交织在同一页上。

核心那一招:先写日记,再改账本

ARIES 的地基是一条近乎无聊的规矩:动账本之前,先把「我要干什么」写进日记,并保证这笔日记先落到磁盘上。日记只往后加、绝不涂改——「我把第 7 页那个数从 3 改成了 5」。有了它,夹生饭就有救:日记里写着、账本上没有的补做;日记里属于半截事务的痕迹倒推撤掉。而日记是顺序写的,比在账本上东改一处西改一处快得多。

三个细节,让补做和撤销真的可靠

一、给每条日记编号,给每页账本盖印章。页眉上盖着一行小字:「我最后一次被改,对应日记第 42 条」。拿日记第 57 条来对:印章是 42,早于 57,说明这笔还没落在这页上,补做;印章若已是 90,说明早做过了,跳过。于是补做十遍和一遍结果一样——这点至关重要,因为恢复途中还可能再断电、再来一遍。

二、先原样重演历史,再回头撤销。它不挑好人坏人,把日记从头到尾原样重演一遍,连注定要撤销的半截事务的改动也照做,先把数据库复原成「断电前最后一瞬」的模样,再把半截事务干净撤掉。为什么多这一步?因为撤销是有前提的:要抹掉一条记录,得先知道它在哪儿、周围长什么样。只挑着补做,数据库会停在一个从未真实存在过的怪状态。像刑侦:先按照片把现场摆回原样,再一步步倒推。

三、撤销本身也写进日记。每撤一步就补记一笔「刚才那笔撤了,下一个该撤第几条」。撤到一半又断电,重启读到最后那笔补记就知道从哪儿接着撤——撤过的整段跳过,绝不重撤。这正是「反复崩溃也一定收敛」的保证。

它换来了什么

有了这套,数据库才敢把内存当内存用:脏数据想什么时候刷盘就什么时候刷(哪怕事务还没提交),提交时也不必傻等数据落盘、只等日记落盘。快,且不怕断电。代价也实打实:每笔改动都要写两遍,这本日记成了全系统最拥挤的一条路,到了几十核的内存数据库时代反成新瓶颈。

一句话记住

动数据前先把改动写进一本只追加的日记并落盘;崩溃后靠每页上的「最后改动编号」印章,把补做变成做几遍都一样的安全动作,先原样重演全部历史复原现场,再回头撤销半截事务,每一步撤销也记进日记——于是无论哪一刻再断电,恢复都能接着跑并收拾干净。

想看三趟恢复的流程图、CLR 指针链和 steal / no-force 的取舍? → 切到精读版