我們知道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