CKH 網誌

PostgreSQL 16 搬到新主機:備份、還原與資料完整性驗證

實測環境與硬體規格

項目實際測試配置
測試日期2026-10-02
作業系統Ubuntu 24.04.5 LTS
主機數量2 台新建隔離 VM;下列資源為每台配置
CPU2 vCPU
記憶體4 GiB
系統磁碟32 GiB;HDD 儲存、VirtIO、ext4
Linux 核心6.8.0-139-generic
PostgreSQLpsql (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)

用兩台獨立 Ubuntu 24.04 主機,將 PostgreSQL 16 的範例資料庫搬到新主機,核對備份雜湊、資料內容、擁有者與索引,再驗證重新開機後的結果。

本文以全新 Ubuntu 24.04 隔離主機和合成資料實測。套件來自經過簽章驗證、符合 Noble 的套件來源;沒有使用正式資料庫或正式網站的帳號。讀者請依自己的環境確認來源與版本。

圖中是測試主機實際 bash PTY 的執行紀錄,由瀏覽器呈現;提示符統一為 lab$,執行結果未改寫。文字命令另行保留,方便複製。

開始前需完成 PostgreSQL 16 的原生安裝與叢集啟動,可先閱讀 Ubuntu 24.04 安裝篇。本系列使用 demo 範例資料庫;需要既有 sample 表的篇章,依 搬機篇的資料建立步驟 準備 100 筆合成資料。請在獨立教學環境操作。

一、先決定搬哪些資料

這次兩邊都是 PostgreSQL 16.15,資料庫叫 demo,擁有者是 app_user。範例有一張 sample 表、100 筆資料與主鍵。這是同主要版本的邏輯搬移;停機時間、正式應用程式切換及跨主要版本升級需要另外評估。

pg_dump 備份單一資料庫,角色屬於叢集層級,需要另外盤點。正式搬移前應停止寫入或安排最後一次一致備份,並記下角色、extension、locale、編碼與應用程式連線設定。PostgreSQL 備份文件

二、在來源主機建立可辨識的測試資料

sudo -u postgres psql -X -v ON_ERROR_STOP=1 <<'SQL'
CREATE ROLE app_user LOGIN;
CREATE DATABASE demo OWNER app_user;
SQL
sudo -u postgres psql -X -v ON_ERROR_STOP=1 -d demo <<'SQL'
SET ROLE app_user;
CREATE TABLE sample(id integer PRIMARY KEY, note text NOT NULL);
INSERT INTO sample SELECT n, 'sample-' || n FROM generate_series(1,100) n;
SELECT count(*) AS rows, sum(id) AS id_sum FROM sample;
SQL

預期是 100 筆、編號總和 5050。上述建置只適用於空白教學環境;不要拿來覆寫已有的角色或資料庫。

三、產生 custom 格式備份與校驗檔

sudo install -d -o postgres -g postgres -m 0700 /var/backups/postgresql/demo
sudo -u postgres pg_dump -Fc -d demo -f /var/backups/postgresql/demo/demo.dump
sudo -u postgres sh -c 'cd /var/backups/postgresql/demo && sha256sum demo.dump > demo.dump.sha256'
sudo -u postgres sh -c 'umask 077; pg_dumpall --globals-only --no-role-passwords > /var/backups/postgresql/demo/globals.sql'
sudo -u postgres pg_restore -l /var/backups/postgresql/demo/demo.dump

角色匯出刻意使用 --no-role-passwords,不帶出密碼驗證值。globals.sql 仍可能包含內部角色名稱、權限與路徑,必須當作私有備份保存;本文不公開實際匯出檔。

圖1:來源主機的 100 筆範例資料與備份目錄內容
圖1:來源主機的 100 筆範例資料與備份目錄內容。實際 PTY 紀錄,點圖可開啟原尺寸。

四、以受保護的管道移交到新主機

實測透過控制器的固定 SSH 指紋與加密 SSH 連線,將備份移交到另一台全新 VM;來源與目的地 SHA-256 相同。自行操作時可使用已驗證主機指紋的 SSH/SCP,檔案全程限制為必要管理者可讀。不要為了傳檔關閉 SSH 主機金鑰驗證,也不要把備份放到網站目錄。

以下假設已將 demo.dump 和 demo.dump.sha256 放進目的地 /var/backups/postgresql/demo,並交由 postgres 擁有。

sudo -u postgres sh -c 'cd /var/backups/postgresql/demo && sha256sum --check demo.dump.sha256'
sudo -u postgres pg_restore -l /var/backups/postgresql/demo/demo.dump

五、先建立必要角色,再還原

此教學只需要一個普通應用角色,所以在目的地建立同名 app_user。先檢視全域匯出再挑選必要角色;不要直接套入整份 globals 而撞到目的地既有的 postgres 或管理角色。

sudo -u postgres psql -X -v ON_ERROR_STOP=1 <<'SQL'
CREATE ROLE app_user LOGIN;
CREATE DATABASE demo OWNER app_user;
SQL
sudo -u postgres pg_restore --exit-on-error --single-transaction \
  -d demo /var/backups/postgresql/demo/demo.dump
sudo -u postgres psql -X -d demo -c 'ANALYZE;'

這裡由 postgres 還原,保留原本物件擁有者;沒有使用 --no-owner。全域匯出沒有密碼,所以真正使用 TCP 登入前,應在目的地以 \password app_user 重新設定密碼,再依 HBA/TLS 規則測試。密碼請互動輸入,不放在命令參數或文章中。pg_restore 選項

六、核對內容、擁有者與索引

sudo -u postgres psql -X -d demo <<'SQL'
SELECT count(*), sum(id), bool_and(note = 'sample-' || id) FROM sample;
SELECT tableowner FROM pg_tables WHERE schemaname='public' AND tablename='sample';
SELECT indexname FROM pg_indexes WHERE schemaname='public' AND tablename='sample';
SQL
pg_isready -h 127.0.0.1 -p 5432
圖2:目的地還原後的筆數、擁有者與可用狀態
圖2:目的地還原後的筆數、擁有者與可用狀態。實際 PTY 紀錄,點圖可開啟原尺寸。

實測還原結果為 100 | 5050 | t,擁有者是 app_user,主鍵索引仍存在。新主機重新開機後,再次確認服務可連線與 100 筆資料,才算完成這次搬移驗證。

這次驗證了什麼

驗證項目結果
兩台不同 VM 的備份 SHA-256 相同通過
100 筆內容、總和與資料規則相同通過
擁有者與主鍵索引保留通過
還原後 ANALYZE 完成通過
重新開機後資料與服務正常通過

實測範圍:驗證了同版本 PostgreSQL、合成資料與兩台 VM 的搬移;未宣稱完成正式應用切換、跨版本升級、extension 相容性或大型資料庫的停機時間測量。

官方參考資料

SQL dump 備份、pg_restore