pg_upgrade — PostgreSQLサーバインスタンスをアップグレードする
pg_upgrade
-b
oldbindir
[-B
newbindir
] -d
oldconfigdir
-D
newconfigdir
[option
...]
pg_upgrade(これまではpg_migratorと呼ばれていました)を使用することで、メジャーバージョンのアップグレード、例えば、12.14から13.10へ、14.9から15.5へのアップグレードで通常必要とされるデータのダンプ/リストアを行うことなく、PostgreSQLデータファイル内に格納されたデータをより最新のPostgreSQLメジャーバージョンに移行できます。 これは、例えば12.7から12.8、14.1から14.5などマイナーバージョンのアップグレードでは必要ありません。
PostgreSQLのメジャーリリースでは通常、システムテーブルのレイアウトをよく変更する、多くの機能が追加されます。 しかし内部データの格納書式はまれにしか変更されません。 pg_upgradeはこの事実を使用して、システムテーブルを新しく作成し、古いユーザデータファイルを単に再利用することで、高速なアップグレードを実施します。 将来のメジャーリリースでついに古いデータ書式を読み取ることができなくなるようにデータ格納書式を変更した場合、pg_upgradeではこうしたアップグレードを扱うことができません。 (コミュニティはこうした状況を防ごうと考えています。)
pg_upgradeは古いクラスタと新しいクラスタとの間で、例えばコンパイル時の設定に互換性があるかどうか、32ビットバイナリか64ビットバイナリかなど、バイナリ互換性があることを確実にするために最善を尽くします。 任意の外部モジュールがバイナリ互換であることも重要ですが、これはpg_upgradeでは検査することができません。
pg_upgradeは9.2.X以降から現時点のPostgreSQLのメジャーリリース(スナップショット版やβリリースを含む)へのアップグレードをサポートします。
pg_upgradeは以下のコマンドライン引数を受け付けます。
-b
bindir
--old-bindir=
bindir
古いPostgreSQLの実行ファイル格納ディレクトリ。PGBINOLD
環境変数
-B
bindir
--new-bindir=
bindir
新しいPostgreSQLの実行ファイル格納ディレクトリ。デフォルトはpg_upgradeのあるディレクトリ。PGBINNEW
環境変数
-c
--check
クラスタの検査のみを行い、データの変更を行いません。
-d
configdir
--old-datadir=
configdir
古いクラスタの設定データディレクトリ。PGDATAOLD
環境変数
-D
configdir
--new-datadir=
configdir
新しいクラスタの設定データディレクトリ。PGDATANEW
環境変数
-j njobs
--jobs=njobs
使用する同時実行プロセスまたはスレッド数。
-k
--link
新しいクラスタにファイルをコピーするのではなく、ハードリンクを使用します。
-N
--no-sync
デフォルトでは、pg_upgrade
はアップグレードされたクラスタのすべてのファイルが安全にディスクに書き込まれるのを待ちます。
このオプションでpg_upgrade
は待たずに戻るようになります。これはより高速ですが、その後のオペレーティングシステムのクラッシュによってデータディレクトリが壊れたままになる可能性があることを意味します。
一般的に、このオプションは試験するには有用ですが、実稼働環境では使用すべきではありません。
-o
options
--old-options
options
古いpostgres
コマンドに直接渡すオプションです。複数の起動オプションが追加されます。
-O
options
--new-options
options
新しいpostgres
コマンドに直接渡すオプションです。複数の起動オプションが追加されます。
-p
port
--old-port=
port
古いクラスタのポート番号。PGPORTOLD
環境変数
-P
port
--new-port=
port
新しいクラスタのポート番号。PGPORTNEW
環境変数
-r
--retain
正常に完了した場合であってもSQLファイルとログファイルを保持します。
-s
dir
--socketdir=
dir
アップグレード中にpostmasterソケット用に利用するディレクトリ。デフォルトは現在の作業ディレクトリです。環境変数PGSOCKETDIR
-U
username
--username=
username
クラスタのインストールユーザの名称。PGUSER
環境変数
-v
--verbose
冗長な内部ログを有効にします。
-V
--version
バージョン情報を表示し、終了します。
--clone
新しいクラスタにファイルをコピーする代わりに、効率的なファイルの複製(システムのいくつかでは「reflink」としても知られています)を使います。
これは、データファイルをほぼ瞬間的にコピーし、古いクラスタに手をつけずに-k
/--link
の速度の利点を与えることになるでしょう、
ファイルの複製はいくつかのオペレーティングシステムとファイルシステムでのみサポートされています。 選択されたもののサポートされていなければ、pg_upgradeの実行はエラーになります。 現在のところ、BtrfsとXFS(のreflinkサポート付きで作られたファイルシステム)のLinux(カーネル4.5以降)と、APFSのmacOSでサポートされています。
--copy
新しいクラスタにファイルをコピーします。
これがデフォルトです。
(--link
および--clone
も参照してください。)
-?
--help
使用方法を表示し、終了します。
pg_upgradeを用いたアップグレードを行う手順を示します。
古いクラスタの移動(省略可能)
バージョンに関連したインストレーションディレクトリ(例えば/opt/PostgreSQL/16
)を使用しているのであれば、古いクラスタを移動する必要はありません。
グラフィカルインストーラはすべて、バージョンに関連したインストレーションディレクトリを使用します。
インストレーションディレクトリがバージョンに関連していない(例えば/usr/local/pgsql
)のであれば、新しいPostgreSQLのインストレーションに干渉しないように、現在のPostgreSQLインストレーションディレクトリを移動しなければなりません。
一度現在のPostgreSQLサーバを停止させていれば、PostgreSQLのインストレーションの名前を変更しても安全です。
古いディレクトリが/usr/local/pgsql
であれば、以下のようにディレクトリ名を変更します。
mv /usr/local/pgsql /usr/local/pgsql.old
ソースからのインストールの場合の新しいバージョンの構築
古いクラスタと互換性を持つようなconfigure
オプションを付けて新しいPostgreSQLソースを構築してください。
pg_upgradeはアップグレードを始める前にすべての設定が互換性を持っていることを確認するためにpg_controldata
を検査します。
新しいPostgreSQLのバイナリのインストール
新しいサーバのバイナリとサポートファイルをインストールしてください。 pg_upgradeはデフォルトのインストレーションに含まれています。
ソースからインストールする場合、独自の場所に新しいサーバをインストールしたければ、以下のようにprefix
を使用してください。
make prefix=/usr/local/pgsql.new install
新しいPostgreSQLクラスタを初期化
initdb
を使用して新しいクラスタを初期化してください。
ここでも、古いクラスタに合うように互換性があるinitdb
のオプションを使用してください。
あらかじめ組み込まれたインストーラの多くは、この手順を自動的に実施します。
新しいクラスタを起動する必要はありません。
拡張共有オブジェクトファイルをインストール
contrib
からのものであろうとその他のソースからのものであろうと、多くの拡張や独自のモジュールは、例えばpgcrypto.so
などの独自の共有オブジェクトファイル(またはDLL)を使います。
古いクラスタがこれらを使用していたのであれば、新しいサーバのバイナリに合った共有オブジェクトファイルを、たいていはオペレーティングシステムのコマンドで、新しいクラスタにインストールしなければなりません。
例えばCREATE EXTENSION pgcrypto
などのスキーマ定義はロードしないでください。これらは古いクラスタから複製されるためです。
拡張アップデートが利用可能であれば、pg_upgradeはこれを報告し、アップデートのために後で実行できるスクリプトを作成します。
独自の全文検索ファイルをコピー
独自の全文検索ファイル(辞書、同義語、類語辞書、ストップワード)を古いクラスタから新しいクラスタにコピーしてください。
認証の調整
pg_upgrade
は古いサーバと新しいサーバに複数回接続します。
このため、pg_hba.conf
内でpeer
認証に設定、あるいは、~/.pgpass
ファイル(34.16参照)を使用するようにした方が良いかもしれません。
両サーバの停止
両サーバが停止していることを確実にしてください。 例えばUnixでは以下を使用します。
pg_ctl -D /opt/PostgreSQL/12 stop pg_ctl -D /opt/PostgreSQL/16 stop
Windowsでは以下
NET STOP postgresql-12 NET STOP postgresql-16
すべての変更を受信するよう、ストリーミングレプリケーションおよびログシッピングのスタンバイサーバは、このシャットダウン中は実行していなければなりません。
スタンバイサーバのアップグレードの準備
スタンバイサーバをステップ 11の節で示した手順でアップグレードする場合は、pg_controldataを実行して、古いスタンバイサーバが、古いプライマリ及びスタンバイのクラスタに同期していることを確認してください。
すべてのクラスタで「Latest checkpoint location」(最終チェックポイント位置)の値が一致することを確認してください。
また、新しいプライマリのクラスタのpostgresql.conf
ファイルでwal_level
をminimal
に絶対に設定しないようにしてください。
pg_upgradeの実行
古いサーバのものではなく、常に新しいサーバのpg_upgradeバイナリを実行してください。
pg_upgradeは古いクラスタおよび新しいクラスタのデータと実行形式ファイルの格納ディレクトリ(bin
)の指定を要求します。
また、ユーザやポート番号の指定や、デフォルト動作のコピーではなくデータファイルのリンクや複製を使用するかどうかを指定することができます。
リンクモードを使用する場合、アップグレードは非常に高速になり(ファイルのコピーがありません)、ディスク容量が少なくなりますが、アップグレード後に新しいクラスタを一度でも実行してしまうと、古いクラスタにアクセスすることができなくなります。
リンクモードはまた、古いクラスタと新しいクラスタのデータディレクトリが同じファイルシステムにあることが必要です。
(テーブル空間およびpg_wal
は異なるファイルシステムに置くことができます。)
複製モードは同じ速度とディスク容量の利点を提供しますが、新しいクラスタを一度実行しても、古いクラスタが使えなくなる訳ではありません。
複製モードはまた、新旧のデータディレクトリが同じファイルシステム内にあることを要求します。
このモードは特定のオペレーティングシステムのファイルシステム上でのみ利用可能です。
--jobs
オプションにより複数のCPUコアを使用して、並行してファイルのコピー・リンク、データベーススキーマのダンプとリストアを行うことができます。
この値の最大値として検討を始める際には、CPUコア数またはテーブル空間数を勧めます。
このオプションはマルチプロセッサを持つマシンで実行している複数のデータベースサーバをアップグレードする時間を大きく減らします。
Windowsユーザの場合、管理者アカウントでログオンしなければなりません。
また、postgres
ユーザとしてシェルを起動し、適切なパスを設定してください。
RUNAS /USER:postgres "CMD.EXE" SET PATH=%PATH%;C:\Program Files\PostgreSQL\16\bin;
そして、以下の例のように、引用符でくくったディレクトリを付けてpg_upgradeを実行してください。
pg_upgrade.exe --old-datadir "C:/Program Files/PostgreSQL/12/data" --new-datadir "C:/Program Files/PostgreSQL/16/data" --old-bindir "C:/Program Files/PostgreSQL/12/bin" --new-bindir "C:/Program Files/PostgreSQL/16/bin"
起動後、pg_upgrade
は2つのクラスタに互換性があるかどうか検証し、その後、アップグレードを行います。
検査のみを行うpg_upgrade --check
を使用することができます。
この場合は古いサーバは稼働中であっても構いません。
またpg_upgrade --check
は、アップグレード後に手作業で行わなければならない調整作業があればその概要を示します。
リンクまたは複製モードを使用する予定であれば、モード固有の検査を有効にするために--check
を付けて--link
または--clone
オプションを使用すべきです。
pg_upgrade
は現在のディレクトリに対する書き込み権限を必要とします。
言うまでもありませんが、アップグレード中はクラスタにアクセスしてはいけません。 意図しないクライアント接続を防ぐために、デフォルトではpg_upgradeは50432ポートでサーバを稼働します。 古いクラスタと新しいクラスタが同時に稼働することはありませんので、両クラスタで同じポート番号を使用することができます。 しかし実行中の古いクラスタを検査する時には、新旧で異なるポート番号でなければなりません。
データベーススキーマのリストア中にエラーが発生した場合、pg_upgrade
は終了しますので、後述のステップ 17で示すように古いクラスタに戻さなければなりません。
再びpg_upgrade
を試すためには、pg_upgradeによるスキーマのリストアが成功するように古いクラスタを変更しなければなりません。
問題がcontrib
モジュールであれば、そのモジュールがユーザデータを格納するために使用されていないことが前提ですが、古いクラスタからそのcontrib
モジュールをアンインストールし、アップグレードした後に新しいクラスタにそれをインストールする必要があるかもしれません。
ストリーミングレプリケーションおよびログシッピングのスタンバイサーバのアップグレード
リンクモードを使用した場合で、ストリーミングレプリケーション(27.2.5参照)またはログシッピング(27.2参照)のスタンバイサーバがある場合、以下の手順に従って、素早くアップグレードすることができます。 スタンバイサーバでpg_upgradeは実行せず、代わりにプライマリでrsyncを実行することになります。 どのサーバもまだ起動しないでください。
リンクモードを使用しなかった場合、rsyncの機能が使えない場合や使いたくない場合、あるいはもっと容易な方法を望む場合は、この節の手順を読み飛ばし、pg_upgradeが完了して新しいプライマリが起動したら、単純にスタンバイサーバを再作成してください。
PostgreSQLの新しいバイナリをスタンバイサーバにインストール
すべてのスタンバイサーバで新しいバイナリとサポートファイルがインストールされていることを確実にしてください。
新しいスタンバイのデータディレクトリが存在しないことの確認
新しいスタンバイのデータディレクトリが存在しないか空であることを確実にしてください。 initdbが実行されている場合は、スタンバイサーバの新しいデータディレクトリを削除してください。
拡張共有オブジェクトファイルのインストール
新しいプライマリのクラスタにインストールしたのと同じ拡張共有オブジェクトファイルを新しいスタンバイにインストールしてください。
スタンバイサーバの停止
スタンバイサーバがまだ実行中なら、上記の手順に従って停止してください。
設定ファイルの保存
スタンバイの設定ディレクトリの設定ファイルで保持する必要のあるもの、例えばpostgresql.conf
(とそれがインクルードしているファイル)やpostgresql.auto.conf
、pg_hba.conf
を保存してください。
これらは次のステップで上書きあるいは削除されるからです。
rsyncの実行
リンクモードを使用する場合、rsyncを使用してスタンバイサーバを素早くアップグレードすることができます。 これを実行するには、古いデータベースクラスタのディレクトリおよび新しいデータベースクラスタのディレクトリより上位にあるプライマリサーバ上のディレクトリで、プライマリ上で各スタンバイサーバに対して以下を実行します。
rsync --archive --delete --hard-links --size-only --no-inc-recursive old_cluster new_cluster remote_dir
ここでold_cluster
およびnew_cluster
はプライマリのカレントディレクトリからの相対パス、remote_dir
はスタンバイサーバ上の古いクラスタと新しいクラスタのディレクトリの上位のディレクトリです。
プライマリとスタンバイの指定したディレクトリより下のディレクトリ構造は一致しなければなりません。
リモートディレクトリの指定の詳細についてはrsyncのマニュアルを参照してください。
例を示します。
rsync --archive --delete --hard-links --size-only --no-inc-recursive /opt/PostgreSQL/12 \ /opt/PostgreSQL/16 standby.example.com:/opt/PostgreSQL
rsyncの--dry-run
オプションを使うことで、そのコマンドが何をするか確認することができます。
rsyncは少なくとも1つのスタンバイに対して、プライマリ上で実行しなければなりませんが、アップグレード済みのスタンバイがまだ起動していなければ、そのスタンバイ上でrsyncを実行して、他のスタンバイをアップグレードすることができます。
これが実行するのはpg_upgradeのリンクモードが作成したプライマリサーバ上の古いクラスタのファイルと新しいクラスタのファイルを接続するリンクについて記録することです。 次にスタンバイの古いクラスタ内の一致するファイルを探し、スタンバイの新しいクラスタ内に対応するリンクを作成します。 プライマリ上でリンクされなかったファイルは、プライマリからスタンバイにコピーされます。 (それらは通常は小さいです。) これにより高速なアップグレードが可能になります。 残念ながらrsyncは一時テーブルやログを取らないテーブルに関連したファイルを不要であるにも関わらずコピーします。 これらのファイルが通常はスタンバイサーバに存在しないからです。
テーブル空間を使用している場合は、各テーブル空間のディレクトリについて、同様のrsyncコマンドを実行する必要があります。 例を示します。
rsync --archive --delete --hard-links --size-only --no-inc-recursive /vol1/pg_tblsp/PG_12_201909212 \ /vol1/pg_tblsp/PG_16_202307071 standby.example.com:/vol1/pg_tblsp
pg_wal
をデータディレクトリの外側に移動している場合は、そのディレクトリについてもrsyncを実行しなければなりません。
ストリーミングレプリケーションおよびログシッピングのスタンバイサーバの設定
ログシッピングのためにサーバを設定します。
(スタンバイはまだプライマリと同期されているので、pg_backup_start()
とpg_backup_stop()
を実行したり、ファイルシステムのバックアップを取得したりする必要はありません。)
レプリケーションスロットはコピーされないため、再作成する必要があります。
pg_hba.conf
の復旧
pg_hba.conf
を変更している場合は、元の認証設定に戻してください。
また新しいクラスタにおけるこの他の設定ファイル、例えばpostgresql.conf
(とそれがインクルードしているファイル)、postgresql.auto.conf
も古いクラスタに合わせるように調整する必要があります。
新しいサーバの起動
ここで新しいサーバが安全に起動できます。 それからrsyncしたすべてのスタンバイサーバを起動できます。
移行後の処理
アップグレード後の処理が必要な場合、pg_upgradeはその終了時に警告を発します。 また、管理者として実行しなければならないスクリプトファイルを生成します。 このスクリプトファイルは、アップグレード後の処理を必要とするデータベースそれぞれに接続します。 各スクリプトは以下を使用して実行しなければなりません。
psql --username=postgres --file=script.sql postgres
スクリプトは任意の順番で実行することができ、また、実行が終わったら削除することができます。
一般的には、再構築用のスクリプトの実行が完了するより前に、再構築用のスクリプトで参照されるテーブルにアクセスすることは安全ではありません。 これを行うと間違った結果が生じたり、性能が劣化することがあり得ます。 再構築用のスクリプトで参照されないテーブルにはすぐにアクセスすることができます。
統計情報
オプティマイザの統計情報はpg_upgrade
により転送されませんので、アップグレード後に統計情報を再生成するコマンドを実行するように指示されます。
新しいクラスタに合わせるために接続パラメータを設定する必要があるかもしれません。
古いクラスタの削除
アップグレード処理が満足いくものであれば、pg_upgrade
の終了時に示されたスクリプトを使用して、古いクラスタのデータディレクトリを削除することができます。
(古いデータディレクトリ内にユーザ定義のテーブル空間がある場合には、自動削除は不可能です。)
(bin
、share
など)古いインストレーションディレクトリも削除できます。
古いクラスタへの戻し
pg_upgrade
を実行した後に古いクラスタに戻したい場合、いくつかの選択肢があります。
--check
オプションが使われた場合、古いクラスタは変更されません。再起動できます。
--link
オプションが使われなかった場合、古いクラスタは変更されません。再起動できます。
--link
オプションが使われた場合、データファイルは古いクラスタと新しいクラスタは共有されるかもしれません。
リンク処理が始まる前にpg_upgrade
が中断すれば、古いクラスタは変更されません。古いクラスタを再起動できます。
新しいクラスタを開始しなかった場合、リンク処理が始まる時に$PGDATA/global/pg_control
に.old
接尾辞が追加される点を除き、古いクラスタは変更されません。
古いクラスタを再度使用するためには、$PGDATA/global/pg_control
から.old
接尾辞を取り除きます。その後で古いクラスタを再起動できます。
新しいクラスタを開始した場合、共有ファイルに書き込んでいますので古いクラスタを使うことは安全ではありません。 この場合、古いクラスタをバックアップからリストアすることが必要でしょう。
pg_upgradeはスキーマのダンプなど様々な作業ファイルを作成し、新しいクラスタのディレクトリのpg_upgrade_output.d
内に保存します。
実行するたびに、ISO 8601に従ってフォーマットされたタイムスタンプ(%Y%m%dT%H%M%S
)の付いた名前の新しいサブディレクトリが作成されます。このサブディレクトリには、生成されたファイルがすべて保存されます。
pg_upgradeが正常に完了した場合、pg_upgrade_output.d
とそれに含まれるファイルは自動的に削除されます。
しかし、問題が発生した場合、そこにあるファイルは有用なデバッグ情報を提供する可能性があります。
pg_upgradeは新旧のデータディレクトリで短命なpostmasterを起動します。
このpostmasterの通信用の一時的なUnixのソケットファイルが、デフォルトでは現在の作業ディレクトリに作られます。
状況に依っては、カレントディレクトリのパス名が有効なソケット名には長過ぎる場合もあるでしょう。
その場合、-s
オプションを使ってソケットファイルをより短いパス名のディレクトリに置くことができます。
セキュリティのため、他のユーザがそのディレクトリを読んだり書いたりできないことを確実にしてください。
(これはWindowsではサポートされていません。)
インストレーションに影響する場合、失敗、再構築、インデックス再作成はすべてpg_upgradeにより報告されます。 テーブルおよびインデックスを再構築するアップグレード後処理スクリプトは自動的に生成されます。 多くのクラスタのアップグレードを自動化することを考えているのであれば、 すべてのクラスタのアップグレードにおいて同一のデータベーススキーマを持つクラスタが同じアップグレード後処理を必要とすることが分かるはずです。 これはアップグレード後処理がデータ自体ではなくデータベーススキーマに基づいているためです。
展開試験を行うのであれば、古いクラスタのスキーマのみをコピーしたものを作成し、ダミーデータを挿入してから、アップグレードを行ってください。
pg_upgradeは次のOIDを参照するreg*
システムデータ型を使うテーブル列を含むデータベースのアップグレードをサポートしません。
regcollation |
regconfig |
regdictionary |
regnamespace |
regoper |
regoperator |
regproc |
regprocedure |
(regclass
、regrole
、regtype
はアップグレード可能です。)
リンクモードを使用したいが、新しいクラスタを起動した時に古いクラスタを変更させたくない場合は、複製モードの使用を検討してください。
もしそれが利用可能でないなら、古いクラスタのコピーを取得してからリンクモードでアップグレードを行ってください。
有効な古いクラスタのコピーを取得するためには、サーバ稼働中にrsync
を使用して古いクラスタの変動があるかもしれないコピーを作成し、古いサーバを停止させた後に、rsync --checksum
を再度実行して一貫性を保つために何らかの変更をコピーに反映させます。
(rsync
はファイル更新時刻の粒度が1秒しかないので--checksum
が必要です。)
例えば26.3.3で説明したpostmaster.pid
など、一部のファイルを除外したいと考えるかもしれません。
スナップショットやコピーは同時、もしくはデータベースサーバが停止しているときに作らなければなりませんが、ファイルシステムがファイルシステムのスナップショットやコピーオンライトファイルコピーをサポートしているのなら、それを古いクラスタとテーブル空間のバックアップをするのに使うことができます。