跳轉到

備份與還原時間窗

一個目標的歷史是一條鏈:依排程進行的完整備份,以及兩次完整備份之間連續不斷的變更串流(Postgres WAL、MySQL binlog)。 凡是被某個完整備份及其後續變更覆蓋的每一秒,都可以還原。這段跨度就是時間點還原時間窗。

gantt
  dateFormat  YYYY-MM-DD HH:mm
  axisFormat  %a %d
  section Full backups
  daily full      :milestone, 2026-10-01 02:07, 0d
  daily full      :milestone, 2026-10-02 02:07, 0d
  daily full      :milestone, 2026-10-03 02:07, 0d
  daily full      :milestone, 2026-10-04 02:07, 0d
  section Change stream
  WAL / binlog segments :active, 2026-10-01 02:07, 2026-10-04 18:00

完整備份

引擎 模式 工具 還原
Postgres 15–17 physical(預設) 透過複製協定執行 pg_basebackup -Ft -X fetch 基礎備份 + WAL 重放,精確到秒
Postgres 15–17 logical pg_dump -Fc,每個資料庫一個物件;支援排除表和選擇性匯出 pg_restore,存在實體鏈時再透過它重放 WAL
MySQL 8.4 logical mysqldump --single-transaction --source-data=2(例程、事件、觸發器) 載入 + binlog 重放,精確到秒

每個備份都會記錄一份清單:資料庫、表、欄、索引、列數估計和大小,以及存在遷移表時的遷移版本。 控制台和 tenax diff 比較的就是這些內容。

變更串流

每個啟用了時間點還原的目標都有一個串流傳輸程式:

  • Postgres:Tenax 自己的 WAL 接收器,基於實體複製槽(ADR 0005)。 複製槽保證串流傳輸程式重啟期間不遺失任何 WAL。
  • MySQL:從上一次完整備份的 binlog 位置開始執行 mysqlbinlog --read-from-remote-server --raw --stop-never。

每個區段寫完即上傳,仍在寫入的區段每隔 partialInterval(預設 60 秒)上傳一次,所以最後一分鐘同樣可以還原。 每個區段都附帶一份摘要:每張表的提交、插入、更新和刪除次數、DDL,以及選用的遮罩列預覽。

如果串流中斷(複製槽遺失、binlog 被清除),Tenax 會把這條鏈標記為斷裂,發出警示(TenaxStreamChainBroken), 啟動一條新鏈並立即進行一次完整備份(原因為 chain-restart)。舊時間窗在斷點之前的部分仍然可以還原。

保留

完整備份依層級保留;變更區段只保留到時間窗所需的時間範圍;其餘一切由垃圾回收清除,但已固定的備份絕不會被刪除。

預設 時間窗 每日 每週 每月 每年
prod 7 天 14 8 12 5
dev 3 天 7 4 3 0
critical 14 天 30 12 24 7

一天中第一個提交的完整備份就是當天的每日備份;一個 ISO 週中的第一個就是當週的每週備份,依此類推。 一個備份可以同時屬於多個層級,不會產生任何複製。固定(tenax pin <id> --reason …)可以讓備份不受層級約束地保留下來。 GC 在刪除前會先把計畫寫入儲存貯體,先刪 manifest 再刪資料,並在一天後清理孤立的和未完成的上傳。

儲存格式

<store prefix>/<org>/<project>/<namespace>/<target>/
  full/<backup-id>/manifest.json            # written last: the commit marker
  full/<backup-id>/data/<database>.zst.age  # dumps or the base backup tar
  full/<backup-id>/inventory.json.zst.age   # also readable with the catalog key
  full/<backup-id>/tags.json                # tiers, pins, verification results
  stream/…/<segment>.zst.age                # WAL / binlog segments and their summaries
  stream/position.json                      # the streamer's confirmed position
  • 壓縮:依策略設定的級別執行 zstd 壓縮,只壓縮一次,在加密之前進行;預設開啟 (ADR 0013)。compression.algorithm: none 則依原樣儲存資料。
  • 加密:每個物件都在用戶端用 age 加密給儲存的接收者。儲存貯體永遠看不到明文。
  • 完整性:每個物件的大小和 SHA-256 都記錄在 manifest 中,每次讀取時都會驗證。
  • 提交:備份只有在寫入 manifest.json 之後才算存在。在此之前發生崩潰只會留下由 GC 清除的孤立物件, 絕不會出現一個看起來完整的備份。

負載控制

備份從不盲目地與正式環境的業務爭搶資源:有依主機、依目標和全域的並發槽、頻寬限制、優先順序、排程時間抖動, 以及一個負載保護機制,在伺服器活躍連線過多、複製延遲過大或存在長時間執行的交易時延後完整備份。 所有這些都在 BackupPolicy 中設定。