数据恢复就是为了在故障时也要保证ACID
checkpoint 存档点
存档点的那个点不好找,
扫描日志去查找没有提交的txn可能花费了很长时间
存档频率不好把握
aries
algrithms for recovery and isolation exploting semantics
数据库恢复原型算法
- WAL 预写日志
steal+no force非强制+窃取
- repeating history during redo
需要回放的回放
- logging changes during undo
跑了一半的事务undo
任务:
- log sequence numbers lsn日志序列号
- normal commit & abort operations 事务正常commit与回滚
- fuzzy CheckPointing 一种优化
- recovery algorithm 算法本身
LSN (log sequence numbers) 日志序列号
flushedLSN,最后一个进磁盘的LSN(意思是之前的都进去了,之后的都没进去)
pageLSN,buffer pool的每个page中,该page上最后一次更新对应的LSN
recLSN,存在同样的位置,从这个页上一次刷盘之后对这个页的第一个操作
lastLSN,在Txn中,事务留下的最后一条日志记录的LSN
masterRecord,在磁盘中,最后的存档点对应的LSN
脏页是可以被写入磁盘的,pageLSN <= flushedLSN
flushedLSN = 16,maseterRecord = 007,这个时候是不能刷盘的,因为之前的LSN没有完全刷入磁盘(buffer pool中的pageLSN != 磁盘中的pageLSN),所以把
所有的日志记录都有编号,
normal execution
- 所有的数据记录都在一个页中
- 磁盘写入是原子的
- 严格2PL
- steal+no-force
commit过程:
在log加一条commit指令
在提交时要保证有关这个事务的所有日志全部都刷入盘中
- 刷盘操作是连续写的
- 日志文件的页是有多条文件记录的
当txn commit完全成功的时候加一条 txn-end
过程:
T4 commit的时候,先写一个commit日志,并把12~15全部刷入磁盘中,并保证flushedLSN=15,用户认为结束了,但是其实还没有结束,因为只有日志落入磁盘了,但是脏页数据还没有落盘
当这一页满了或者其他情况,要讲buffer pool中的page放入磁盘的时候要在日志中加入TXN-END标识符表示彻底结束了
这时候就可以删除之前的内存日志缓存
txn abort:
首先回滚只是特殊情况,我们要在日志再加一个字段:prevLSN
,代表的是这条日志的上一条日志是几号,类似链表记录上一条地址,因为日志是所有txn共用的,所以更容易实现回滚
原则:回滚是可以回滚的,但是回滚过程也是要记录的,记录在CLR中
CLR(compensation log records) 清空日志
CLR是不需要强制刷盘的,目的就是记录回滚日志
回滚的具体操作:
- 写一个ABORT日志
- 反向回滚日志,并追加清理日志
- 清理完成后加TXN-END
清理日志是不需要回滚的
fuzzy checkpointng
模糊存档点(对存档点的优化)
为什么checkpoint会影响速度:
- 打点的时候要停下其他的所有txn
- 要让所有正在做的都做完
- 讲脏页刷入磁盘
改进方案:
- 不要等待所有进行中的事务都结束,仅仅让他们停下就行了,加锁刷盘
需要做一些工作:
- ATT(active transaction table) 正在执行的活动事务表
- DPT(dirty page table) 脏页表
ATT : 活动事务表
- txnId 事务id
- status 模式
- lastLSN 最后的LSN
当事务这的做完(TXN-END),才能删ATT
status 状态:
- R-running 运行中
- C-committing 提交中
- U-candidate for undo 尚未提交(undo 候选者)
DPT 脏页表
- recLSN,代表着第一个让这个页变脏的LSN
就是在checkpoint的时候加了ATT与DPT
能够了解到T2与T3是依旧活跃的,p22是已经进去了
原本策略是checkpoint要讲所有脏页与事务都要完成,现在是允许不做完
新的想法:fuzzy checkpoints 模糊的检查
- checkpoint-begin
- checkpoint-end
可以发现之间是有其他事务在进行操作等待,记录操作之间有那些操作在进行,但是如果这个txn是在之间start时,就不记录,用checkpoint-begin做那个操作点
ARIES 算法 :
- analysis 分析,读WAL文件的MasterRecord,找那个begin,分析上下日志
- redo
- undo
analysis :
找到last successful checkpoint
如果找了了一个TXN-END,表示这个事务已经成功结束了,就不用管这个txn(从ATT把他删了就行)
- 把事务放入ATT中暂时让他变成undo状态
- 如果发现commit,就把他的状态变成commit
如果发现有修改的语句,如果这个页没在DPT中,就把这个页放入DPT中,记录这个页的LSN放入recLSN
分析阶段做完就变成:
- ATT记录到数据库崩溃时,系统有多少事务是活着的
- DPT记录到数据库崩溃时,系统有多少脏页没进磁盘
redo phase:
把需要回滚和不需要回滚的都重做,CLR也要重做
把脏页从recLSN开始重做,有两个特殊情况
- DPT表中没有这个页,就不用处理这个页(本就不是脏页)
- DPT中有这个页,但是LSN比recLSN还小就不用管
状态是C的就redo,并写一个TXN-END,并从ATT中移除
undo phase:
从ATT中找到状态为U的事务undo,可以用lastLSN找那个记录
这时候宕机
1,做表
undo T2先回滚60,再记录下一个20,T3回滚50,T3 回滚结束,刷盘
但是这个时候,T3回滚完了,又停电了,T2怎么办,重启之后重新做表:继续操作
三个时间段断电都无所谓
大家都不要写超长的事务,对大家都好