PostgreSQL11から12へのアップグレードの手順

# はじめに

以下の投稿で構築したPostgreSQL11の環境を12へアップグレードしたときのメモです。

- [CentOS 7にPostgreSQL11をインストールする](https://qiita.com/mkyz08/items/519bd8d6a7140c8ed57e)


# メジャーバージョンアップでの注意点

11から12へのメジャーバージョンアップでは、単純にPostgreSQLのモジュールを入れ替えるだけでは対応できません。メジャーバージョンが異なる場合は、データベースクラスタに互換性がないためです。
メージャーバージョンアップの際は以下に注意します。

- 機能の変更

メジャーバージョンアップでは機能が追加・変更されたり、システムカタログが変わるなどの影響がある変更が発生することが多いです。変更点については、事前にリリースノートを確認しておきます。
（今回は開発環境だからとりあえずアップグレードしてから考えますが・・・）

- PostgreSQLのパラメータの変更

メジャーバージョンアップではパラメータが追加・削除されている場合があるので、現状の設定ファイルを修正が必要となる場合があります。

- 拡張モジュールの互換性

pg_repack, pg_statsinfoなどの各種拡張モジュールを利用することが多いと思います。メジャーバージョンアップした場合、拡張モジュールが新しいバージョンに対応していないことがあります。その場合は最新版に入れ替えるなどの処置が必要となります。
新しいバージョンに対応していない場合は、「drop extension」であらかじめ削除しておく等の対応が必要となります。また、拡張モジュールがバージョンアップしている場合は、「alter extension ～～ update」を実行します。


# アップグレードの方法

メジャーバージョンをアップグレードする方法は主に以下の2つあります。

- 論理バックアップを取得し、新しいバージョンの環境にリストアする方法
- メジャーバージョンアップ用のpg_upgradeというツールを使用する方法

論理バックアップを用いた方法は、簡単ですがデータ量が多いとバージョンアップに時間がかかります。一方、pg_upgradeでは高速に移行でき大規模データにも対応できるすることができます。

今回は開発環境用なので論理バックアップで十分なのですが、せっかくなのでpg_upgradeを試してみたいと思います。


# pg_upgradeを用いたアップグレードの手順

- 旧バージョンのPostgreSQLを停止
- 新バージョンをインストール
- 新しいPostgreSQLクラスタを初期化
- 新バージョンのPostgreSQLを停止
- pg_upgradeを実行

他に認証の設定、postgresql.confや拡張モジュールの設定等を行います。


まず、PostgreSQL11を停止します。

```
# systemctl stop postgresql-11.service
```

次にPostgreSQL12をインストールします。インストール手順は雑に書いているので他のサイトを参考にしてください。

```
# yum -y install postgresql12-server postgresql12-contrib
# systemctl enable postgresql-12.service
# PGSETUP_INITDB_OPTIONS="-E UTF8 --no-locale" /usr/pgsql-12/bin/postgresql-12-setup initdb
```

pg_upgradeを使用してアップグレードを実施します。
以下のコマンドでは旧バージョンから新バージョンへのdataディレクトリにコピーされます。
"-l"オプションを利用するとリンクモードで実行され、直接dataディレクトリがバージョンアップします。リンクモードを利用すると高速にアップグレードを完了させることができます。

```
/usr/pgsql-12/bin/pg_upgrade -d /var/lib/pgsql/11/data \
 -D /var/lib/pgsql/12/data -b /usr/pgsql-11/bin -B /usr/pgsql-12/bin

-d : 旧バージョンのdataディレクトリを指定する。
-D : 新バージョンのdataディレクトリを指定する。
-b : 旧バージョンのbinを指定する。
-B : 新バージョンのbinを指定する。
```

実行結果は以下のようになります。

```
Performing Consistency Checks
-----------------------------
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
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

If pg_upgrade fails after this point, you must re-initdb the
new cluster before continuing.

Performing Upgrade
------------------
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
Copying user relation files
                                                            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

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    ./analyze_new_cluster.sh

Running this script will delete the old cluster's data files:
    ./delete_old_cluster.sh

```

pg_upgradeにより統計情報はコピーされないため、アップグレード後に再生成するためのスクリプトが生成されます。
自動生成された以下のスクリプトを実行します。

```
$ ./analyze_new_cluster.sh
```

また、旧バージョンのデータベースクラスタを削除する以下のスクリプトも生成されます。
必要に応じて実行します。

```
$ cat delete_old_cluster.sh
#!/bin/sh

rm -rf '/var/lib/pgsql/11/data'
```


# 最後に

開発環境だったので考慮していませんが、ロジカルレプリケーションによるローリングアップデート、スタンバーサーバへお移行など、本番環境であれば色々と検討すべきこともあるかと思います。


# 参考

- [PostgreSQL 11.5文書 pg_upgrade](https://www.postgresql.jp/document/11/html/pgupgrade.html)
- [［改訂新版］内部構造から学ぶPostgreSQL 設計・運用計画の鉄則](https://gihyo.jp/book/2018/978-4-297-10089-6)
- [PostgreSQL徹底入門 第4版](https://www.shoeisha.co.jp/book/detail/9784798164090)
- WEB+DB PRESS vol.108 詳解PostgreSQL