論理レプリケーションによるほぼ無停止のメジャーバージョンアップグレード
PostgreSQLアップグレードコマンド
# 0) On the old version wal_level = logical (restart); every table needs a PRIMARY KEY or REPLICA IDENTITY
# 1) Move roles and schema to the new version (a 'role postgres already exists' error is expected):
pg_dumpall -h <old_host> --globals-only | psql -h <new_host> -X -d postgres
pg_dump -h <old_host> --schema-only --create -d <db> | psql -h <new_host> -X -d postgres
# 2) Publication on the old version, subscription on the new version (initial copy + continuous stream):
psql -h <old_host> -d <db> -X -c "CREATE PUBLICATION upg_pub FOR ALL TABLES;"
psql -h <new_host> -d <db> -X -c "CREATE SUBSCRIPTION upg_sub CONNECTION 'host=<old_host> dbname=<db> user=<repl_user>' PUBLICATION upg_pub;"
# 3) Wait until all tables are 'r' (ready) and lag is ~0:
psql -h <new_host> -d <db> -X -c "SELECT srsubstate, count(*) FROM pg_subscription_rel GROUP BY 1;"
psql -h <old_host> -d <db> -X -c "SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lag FROM pg_replication_slots WHERE slot_name = 'upg_sub';"
# 4) Cutover: stop application writes, confirm lag = 0, synchronize sequences (logical-sync-sequences)
# 5) Drop the subscription (the remote slot is dropped too), point the application to the new server:
psql -h <new_host> -d <db> -X -c "DROP SUBSCRIPTION upg_sub;"概要
新しいバージョンで空のクラスタを構築し、スキーマを移し、論理レプリケーションで旧バージョンからデータを継続的にストリーミングする。最終の切り替え手順(書き込み停止、シーケンス同期、接続先の変更)のみが短い停止を引き起こす。逆方向の2つ目のレプリケーションで切り戻しの経路を確保できる。
使用する場面
pg_upgradeに必要な停止時間が許容できないとき、新しいハードウェア/OSへの移行を同時に行うとき、複数のメジャーバージョンを飛び越えるときに。
注意
DDL、シーケンス、ラージオブジェクト、マテリアライズドビューの内容はレプリケートされないため、移行中はスキーマを凍結する。主キー/replica identityのない表では、パブリッシャでUPDATE/DELETEが失敗する。大規模データベースでは初期コピーに時間がかかり、旧サーバーでWALとcatalog_xminを保持する。データベースごとに個別のパブリケーション/サブスクリプションが必要。切り替え前に行数/チェックサムを比較する。