PostgreSQL10 から PostgreSQL12 へのアップグレード手順(pg_upgrade)

古いPostgreSQLのバージョンがインストールされている開発マシンがあったので、pg_upgradeの公式ドキュメントを参考に、PostgreSQL10.15 から PostgreSQL12.5 に移行してみました。

ドキュメントに よると

pg_upgradeは8.4.X以降から現時点のPostgreSQLのメジャーリリース(スナップショット版やβリリースを含む)へのアップグレードをサポートします。

ということで、古めのバージョンであってもpg_upgradeで一気にバージョンを上げられます。

前提

  • 環境: Ubuntu 18.04 LTS デスクトップ
  • 移行前バージョン: PostgreSQL10.15
  • 移行後バージョン PostgreSQL12.5

バックアップを取得

念の為全DatabaseのDumpバックアップを取っておきます。

$ pg_dumpall > backup.sql

postgresql12をインストール

UbuntuへのPostgresqlのインストールは、公式の手順に従いました。

GPG keyを追加して、aptのsource.listにリポジトリを追加します。

$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |sudo tee  /etc/apt/sources.list.d/pgdg.list

このリポジトリには

といった一般的なパッケージやサードパーティアドオンのような様々なパッケージが含まれているようです。

apt updateして、postgresql12をインストールします。

$ sudo apt update
$ sudo apt -y install postgresql-12 postgresql-client-12

インストールが終わったら、念の為がpostgresql12のクラスタサービスが起動しているか確認します。

$  systemctl status postgresql@12-main.service 
● postgresql@12-main.service - PostgreSQL Cluster 12-main
   Loaded: loaded (/lib/systemd/system/postgresql@.service; indirect; vendor pre
   Active: active (running) since Sat 2021-01-02 12:13:16 JST; 14min ago
  Process: 19223 ExecStop=/usr/bin/pg_ctlcluster --skip-systemctl-redirect -m fa
  Process: 22868 ExecStart=/usr/bin/pg_ctlcluster --skip-systemctl-redirect 12-m
 Main PID: 22877 (postgres)
    Tasks: 7 (limit: 4915)
   CGroup: /system.slice/system-postgresql.slice/postgresql@12-main.service
           ├─22877 /usr/lib/postgresql/12/bin/postgres -D /var/lib/postgresql/12
           ├─22882 postgres: 12/main: checkpointer   
           ├─22883 postgres: 12/main: background writer   
           ├─22884 postgres: 12/main: walwriter   
           ├─22885 postgres: 12/main: autovacuum launcher   
           ├─22886 postgres: 12/main: stats collector   
           └─22887 postgres: 12/main: logical replication launcher

バージョンを戻すことを考慮に入れて一応postgresqlサービスの状態を確認したうえで、停止しておきます。

$ systemctl is-enabled postgresql
enabled

$ sudo systemctl stop postgresql.service

アップグレード

postgresユーザでpg_upgradeを実行します。

$ sudo su postgres

 /usr/lib/postgresql/12/bin/pg_upgrade \
     --old-datadir=/var/lib/postgresql/10/main \
     --new-datadir=/var/lib/postgresql/12/main \
     --old-bindir=/usr/lib/postgresql/10/bin \
     --new-bindir=/usr/lib/postgresql/12/bin \
     --old-options '-c config_file=/etc/postgresql/10/main/postgresql.conf' \
     --new-options '-c config_file=/etc/postgresql/12/main/postgresql.conf'

整合性チェックを実行しています。
-----------------------------
Checking cluster versions                                   ok
Checking database user is the install user                  ok
Checking database connection settings                       ok
Checking for prepared transactions                          ok
Checking for reg* data types in user tables                 ok
Checking for contrib/isn with bigint-passing mismatch       ok
Checking for tables WITH OIDS                               ok
Checking for invalid "sql_identifier" user columns          ok
Creating dump of global objects                             ok
Creating dump of database schemas
                                                            ok
Checking for presence of required libraries                 ok
Checking database user is the install user                  ok
Checking for prepared transactions                          ok
Checking for new cluster tablespace directories             ok

この後pg_upgradeが失敗した場合は、続ける前に新しいクラスタを
initdbで再作成する必要があります。

アップグレードを実行しています。
------------------
Analyzing all rows in the new cluster                       ok
Freezing all rows in the new cluster                        ok
Deleting files from new pg_xact                             ok
Copying old pg_xact to new server                           ok
Setting next transaction ID and epoch for new cluster       ok
Deleting files from new pg_multixact/offsets                ok
Copying old pg_multixact/offsets to new server              ok
Deleting files from new pg_multixact/members                ok
Copying old pg_multixact/members to new server              ok
Setting next multixact ID and offset for new cluster        ok
Resetting WAL archives                                      ok
Setting frozenxid and minmxid counters in new cluster       ok
Restoring global objects in the new cluster                 ok
Restoring database schemas in the new cluster
                                                            ok
ユーザリレーションのファイルをコピーしています
                                                            ok
Setting next OID for new cluster                            ok
Sync data directory to disk                                 ok
Creating script to analyze new cluster                      ok
Creating script to delete old cluster                       ok

アップグレードが完了しました
----------------
オプティマイザーの統計は、pg_upgrade では転送されません。そのため
新サーバーを起動した後、./analyze_new_cluster.sh を動かすことを検討してください。


このスクリプトを実行すると、旧クラスタのデータファイル ./delete_old_cluster.shが削除されます:

アップグレードが終わったので、postgresユーザから一般ユーザに戻します。

  exit

新しくPostgreSQLバージョンのクラスタのポートがデフォルトポートではないため、postgresql.confのport番号を変更します。

$ sudo vim /etc/postgresql/12/main/postgresql.conf
port = 5433                             # (change requires restart)
=> port = 5432                             # (change requires restart)

同様にpostgresql10のポートも変更します。

$ sudo vim /etc/postgresql/10/main/postgresql.conf
port = 5432                             # (change requires restart)
=> port = 5433                             # (change requires restart)

もし、他にもpostgresql.confを変更している箇所があったり、rootユーザパスワードの認証なしでログインできる等の設定をpg_hba.confで行っている場合は、PostgreSQL12の方でも手動変更しておきます。

再度postgresサービスを起動し、接続を確認してみます。

sudo systemctl start postgresql.service

再度、postgresユーザに戻りpsqlコマンドがpostgresql12の方に接続しに行っているか確認します。

$ sudo su postgres
$  psql -c "SELECT version();"
PostgreSQL 12.5 (Ubuntu 12.5-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit

続いて、pg_upgrade実行時に生成されたanalyze_new_cluster.shを実行し、オプティマイザの統計情報を収集しておきます。

$ ./analyze_new_cluster.sh
vacuumdb: データベース"calendar_development"の処理中です: 最適化のための情報を最小限生成します(1対象)
vacuumdb: データベース"calendar_development"の処理中です: 最適化のための情報を最小限生成します(1対象)
〜〜〜
vacuumdb: データベース"world_myroom_development"の処理中です: 最適化のための情報をデフォルト数(全て)生成します

Done

postgresql10の削除

接続が確認できたらpostgresql10は不要なので削除します。

$ sudo apt-get remove postgresql-10 postgresql-server-dev-10
$ sudo rm -rf /etc/postgresql/10/

再度、postgresユーザに戻って、pg_upgrade時に生成されたdelete_old_cluster.shを実行しておきます。

$ sudo su postgres
./delete_old_cluster.sh

参考資料