DB2如何进行crash recovery原理浅析(转载)
跟大家一样,我也很好奇DB2是如何做crash recovery的。最近看了一点 dabase crash recovery的资料,我把我对数据库 recovery的理解贴出来跟大家讨论讨论,这样可以帮助大家更好的理解DB2的行为。也希望实验室的专家们能够多给我们讲点这方面的知识。
首先,讲一下几个概念:
1、dirty page table,每一个修改过的DATA PAGE在这个表里有一个记录,而且每个页第一次变脏的LSN(称作RECLSN)也记录在里面。
2、Transaction table,当前活动的事务都会在这个表里有一条记录,而且还记录这个事务当前的最大的LSN和需要UNDO的最大LSN。每次事务完成(commit或rollback完成)就会把这个transaction从表里删掉。
3、PAGE LSN,每个页在被更新时,会把对应的LSN记在page里,就是page LSN,就是说这个page LSN反映了这个页的最近一次修改。数据库是根据这个判断页需要不需要实际REdo的。
4、Check Point,每次check point会在日志里记一条 begin checkpoint的log。然后会把dirty page table和transaction table 刷到硬盘上。然后在日志里记一条end checkpoint 记录。
5,CLR。每次事务被rollback时,每undo一个log record,会记一个CLR(补充日志),这个日志包含了undonextlsn,指向下一个将要被undo的log lsn。CLR是REDO ONLY的,就是只会被REDO,不会UNDO它。这也说明了事务在rollback的时候也是要记日志的。
6、每个log record有一个prevLSN指向与这个Log Record处于同一事务的前一个log LSN。数据库通过这个LSN来进行事务回滚。prevLSN是0表示这是事务开始的第一个log record。
数据库recovery分为三个阶段:
analysis 阶段:
把dirty page table 和transaction table清空。
找到最近的一次begin checkpoint的日志(这个信息记录在一个固定的地方,每次checkpoint完成会更新它),然后开始顺序向后扫描:
如果发现LSN所属事务不在transaction table里(Log里记有transactionid),往transaction table里插一条记录。
如果发现LSN对应的pageid不在dirty page table里,往dirty page table插入一条记录
如果是普通的update log record,修改transaction table里的需要UNDO的最大LSN为当前LSN。
如果是CLR,修改transaction table里的需要UNDO的最大LSN为CLR的undonextlsn。
如果是end checkpoint的记录,说明这次checkpoint是完整的,从磁盘中读出transaction table
和dirty page table 更新当前的dirty page table 和transaction table。
如果是end记录(表示事务已经提交或完全回滚)则从transaction table里把对应的transaction删除。
其他处理。。。。。。。。。。。。。。
返回最小的dirty page table里的reclsn给REDO过程处理(这个应该就是minbufflsn)。
REDO阶段,:
从minbufflsn开始,向前顺序扫描,一直到故障发生点结束。
如果是普通的update log record或者是CLR。
检查dirty page table里的recLSN是否小于等于log record的LSN
如果是,检查页的PAGE LSN是否小于log record的LSN,如果小于,则进行实际的redo动作。
UNDO阶段:
找到transaction表的所有事务中最大的需要UNDO的最大LSN,记为 CURRENT LOG。
如果是普通的udpate 记录,
进行实际UNDO操作,
记一条CLR信息,
修改对应page的page LSN为CLR的LSN。
修改transaction table里的该事务的最大LSN为CLR的LSN。
修改transaction table里的该事务的最大需要UNDO的LSN为 CURRENT LOG的prevLSN。
如果是CLR记录(这个需要跳过,因为在REDO里已经做了)
修改transaction table里的该事务的最大需要UNDO的LSN为CLR的undonextlsn。
如果CURRENT LOG的prevLSN是0,则写一条END记录,表示这个事务已经完全回滚完成,从transaction table里把对应的transaction删除。
重复以上undo过程,直到transaction table为空。
这只是大体做法,实际crash recovery要考虑的事情非常多,比如一个update 动作引起多个页变动该怎么办(比如往索引页里插入一条记录引起索引树的分裂)。该怎么记日志?怎么回滚。又比如做drop table时,你不可能把这个表的整个内容记下来以便去回滚,还有一些锁的问题需要考虑等等。
crash recovery的难点就是数据库的更改动作非常多,要以一种合理而且能回退的方式记下来,本身就比较难,加上故障随时可能发生,要又好又快的完成crash recovery确实是非常不容易的事情。
另外,以上仅仅是理论上的过程,DB2的具体实现肯定有很多不一样的地方,这个就需要实验室的专家们给我们讲讲了。
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐