Share Notes

chundev

View the Project on GitHub latteouka/share-notes

PG 17 增量備份在 Standby 上的 WAL Timeline 陷阱

日期:2026-03-23 環境:PostgreSQL 17.2, CNPG Operator, K3s


TL;DR

pg_basebackup --incremental 在 Standby 執行時,如果兩次備份之間 WAL 活動不足,會因為 timeline 不一致而失敗。錯誤訊息是 manifest requires WAL from final timeline X ending at Y, but this backup starts at Z。解法:改從 Primary 執行增量備份(負擔極小)。


錯誤訊息

pg_basebackup: error: could not initiate base backup: ERROR:
  manifest requires WAL from final timeline 2 ending at 0/65000000,
  but this backup starts at 0/64000028
HINT: This can happen for incremental backups on a standby
  if there was little activity since the previous backup.
pg_basebackup: removing contents of data directory "/backups/incremental-..."

背景

備份架構:CNPG 2 instances(Primary + Replica),備份從 Replica 執行(不影響 Primary 效能)。

設定 summarize_wal=on 後,Full backup 成功產生 backup_manifest。但緊接著執行增量備份就失敗了。


原因分析

因素 說明
WAL timeline Standby 有自己的 recovery timeline(通常是 timeline 2)。Full backup 的 manifest 記錄了「這個 timeline 上 WAL 到了哪裡」
WAL 位置延遲 Standby 的 WAL replay 可能落後 Primary。如果兩次備份之間活動量少,Standby 的 WAL 位置可能還沒追上 manifest 記錄的結束點
時機問題 Full backup 時產生 checkpoint 推進了 WAL 位置,但 Standby 還來不及 replay 到那個點

核心問題:增量備份要求「當前 WAL 位置 >= manifest 記錄的結束位置」,但 Standby 的 WAL replay 是非同步的。


嘗試與解法

嘗試 結果 原因
❌ 從 Replica 執行 失敗 WAL timeline 不一致
❌ 等幾秒後重試 仍可能失敗 低活動量時 WAL 推進很慢
✅ 改從 Primary 執行 成功 Primary 的 WAL 位置一定 >= manifest

改從 Primary 執行增量備份的影響:

指標 Full backup (從 Replica) 增量備份 (從 Primary)
備份大小 23 MB 556 KB
耗時 ~10s ~3s
Primary CPU 影響 極小(只讀變更區塊)
Primary IO 影響 < 1 MB 讀取

增量備份只傳輸變更區塊(556 KB vs 23 MB = 2.4%),對 Primary 的負擔可以忽略。


最終架構

Full backup (每週日)   → 從 Primary → NFS → 產生 backup_manifest
                                         → 更新 /backups/latest-manifest symlink
增量備份 (每 4 小時)   → 從 Primary → NFS → 基於 latest-manifest
                                         → 更新 latest-manifest(鏈式)
pg_dump (每日)         → 從 Primary → NFS → 獨立,不依賴 manifest

關鍵:Full 和 Incremental 必須從同一台 server 執行,否則 manifest 的 timeline 會不一致。


學到的事


參考資料