我们知道postgresql是支持任意时间点恢复的,那么背后的原理是什么?
本文将对pg的时间点恢复进行详细的讲解,帮助用户理解。
本文涉及源码参考postgresql 9.2.2版本.
我们知道postgresql 支持pitr, 基于时间点的恢复. 通过配置recovery.conf可以指定3种恢复目标, 如下 :
其中recovery_target_time和recovery_target_xid可以指定recovery_target_inclusive参数, 如下 :
默认为true取自src/backend/access/transam/xlog.c :
为什么recovery_target_name不能指定recovery_target_inclusive参数?
而recovery_target_time和recovery_target_xid可以指定recovery_target_inclusive参数呢?
首先要解释一下, 什么情况下恢复可以截止.
只在三种情况恢复可以截止 :
然后这些信息从哪里来呢? 它们都取自xlog的头数据xlogrecord中的sl_rmid和xl_info :
src/include/access/xlog.h
只有在这三个状态下, 恢复允许进入截止判断.
commit/abort/xlog_restore_point;
这个逻辑来自recoverystopshere函数 :
恢复截止的处理函数recoverystopshere中包含了这三个状态的判断, 如下 :
src/backend/access/transam/xlog.c
commit和abort很好理解, 就是事务结束时状态, resotre point的信息则来自xlogrestorepoint函数,
在使用postgresql内建的pg_create_restore_point函数创建还原点时用到xlogrestorepoint :
src/backend/access/transam/xlogfuncs.c
经过以上介绍以后, 我们知道recoverystopshere开头部分的逻辑决定了pitr恢复可以选择截止在:
1. 事务结束时(commit/abort);
2. 或者是用户使用pg_create_restore_point创建的还原点;
recoverystopshere接下来的部分针对recovery.conf中的配置, 判断是否截止恢复.
在文章开头我们还提到了3个还原目标(target) :
(recovery_target_xid, recovery_target_time, recovery_target_name)
1. 未设置任何截至目标, 只返回false, 所以不会停止
recovery_target_unset 取自
2. recovery_target_xid 与 xlogrecord->xl_xid进行比较.
xid作为恢复目标时, recoverytargetinclusive只影响日志输出(recoverystopafter).
原因是xid是按事务启动顺序分配的, 而不是按事务结束顺序分配. 并且这种target下面截止只可能在commit/abort.
所以只要达到这个xid并且状态是commit/abort时, 就返回true.
*includethis = recoverytargetinclusive;只影响了日志输出. 而不是包含和不包含的意思.
日志输出时, 判断recoverystopafter :
3. recovery_target_name 与 xlogrecdata->data进行比较.
如果数据库中有多个重复命名的还原点, 遇到第一个则停止.
同时因为还原点的信息写在单独的xlog数据块中, 不是一条transaction record块, 所以也没有包含或不包含的概念, 直接截止.
不需要判断recovery_target_inclusive .
4. recovery_target_time 与 xl_xact_commit_compact->xact_time进行比较.
因为在同一个时间点, 可能有多个事务commit/abort. 所以recovery_target_inclusive 在这里起到的作用是 :
截止于这个时间点的第一个提交的事务后(包含这个时间点第一个遇到的提交/回滚的事务);
或者截止于这个时间点提交的最后一个事务后(包括这个时间点提交/回滚的所有事务).
其中事务结束时间来自这个数据结构 :
src/include/access/xact.h
从以上逻辑看到, recoverytargetinclusive只有当恢复目标是xid或者time时可以指定.
目标是target name时不需要指定.
1. src/include/catalog/pg_control.h
2. src/include/access/xlog.h
3. src/include/access/rmgr.h