1サーバで複数バージョンのPostgreSQLを使い分ける方法

# はじめに

PostgreSQL は、下図の通り 5つのバージョンが Supported Version です。また、新しいバージョンの Development Version が存在する場合もあります。PostgreSQL を使用したアプリケーションやシステムの開発では、PostgreSQL の各バージョンでテストを行う必要があります。
そこで、複数バージョンの PostgreSQL をインストールして、使い分ける方法を備忘録としてまとめました。
今回は、Supported Version (9.6, 10, 11, 12, 13) と Development Version (14) の6つのバージョンを簡単に環境を構築するために、PostgreSQL用アカウントを作成せず、自分のアカウントを使用して、PostgreSQLをソースコードからインストールします。

![PostgreSQL_multi_version1b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308856/f0e9fba1-5545-13f5-f876-ef847a410799.png)

![PostgreSQL_multi_version1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308856/abbeb206-0c75-2f72-17aa-8de24f4ab3b3.png)

# 環境

OS は、Ubuntu 20.04 を使用しています。

```bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
```

# 事前準備
PostgreSQLに必要なパッケージをインストールします。

```bash
$ sudo apt install libreadline-dev zlib1g-dev bison flex
```

PostgreSQLのインストールと実行に必要なディレクトリを作成します。src はソースコードの格納先、pgsql は PosthreSQLのインストール先、data はデータベースクラスタの格納先としています。

```bash
$ cd $HOME
$ mkdir src
$ mkdir pgsql
$ mkdir data
```

# PostgreSQLのインストール
PostgreSQLのソースコードのアーカイブファイルを入手して、アーカイブファイルを展開します。今回、インストールするバージョンは、9.6.22, 10.17, 11.12, 12.7, 13.2, 14beta2 です。13.2 はあとで、13.3 へ置き換えます。

```bash
$ cd src
$ wget https://ftp.postgresql.org/pub/source/v9.6.22/postgresql-9.6.22.tar.gz
$ wget https://ftp.postgresql.org/pub/source/v10.17/postgresql-10.17.tar.gz
$ wget https://ftp.postgresql.org/pub/source/v11.12/postgresql-11.12.tar.gz
$ wget https://ftp.postgresql.org/pub/source/v12.7/postgresql-12.7.tar.gz
$ wget https://ftp.postgresql.org/pub/source/v13.2/postgresql-13.2.tar.gz
$ wget https://ftp.postgresql.org/pub/source/v14beta2/postgresql-14beta2.tar.gz
$ tar xvzf postgresql-9.6.22.tar.gz 
$ tar xvzf postgresql-10.17.tar.gz 
$ tar xvzf postgresql-11.12.tar.gz 
$ tar xvzf postgresql-12.7.tar.gz 
$ tar xvzf postgresql-13.2.tar.gz 
$ tar xvzf postgresql-14beta2.tar.gz 
```

PostgreSQLをビルドします。configure の実行時に prefix オプションで PostgreSQL のインストール先を指定します。今回は、$HOME/postgres/postgresql-(バージョン番号) とします。

PostgreSQL 9.6.22 インストール

```bash
$ cd $HOME/src/postgresql-9.6.22
$ ./configure --prefix=$HOME/pgsql/postgresql-9.6
$ make
$ make install
```
PostgreSQL 10.17 インストール

```bash
$ cd $HOME/src/postgresql-10.17
$ ./configure --prefix=$HOME/pgsql/postgresql-10
$ make
$ make install
```
PostgreSQL 11.12 インストーを

```bash
$ cd $HOME/src/postgresql-11.12
$ ./configure --prefix=$HOME/pgsql/postgresql-11
$ make
$ make install
```
PostgreSQL 12.7 インストール

```bash
$ cd $HOME/src/postgresql-12.7
$ ./configure --prefix=$HOME/pgsql/postgresql-12
$ make
$ make install
```
PostgreSQL 13.2 インストール

```bash
$ cd $HOME/src/postgresql-13.2
$ ./configure --prefix=$HOME/pgsql/postgresql-13
$ make
$ make install
```
PostgreSQL 14beta2 インストール

```bash
$ cd $HOME/src/postgresql-14beta2
$ ./configure --prefix=$HOME/pgsql/postgresql-14
$ make
$ make install
```

# データベースクラスタの作成
各バージョンのデータベースクラスタを作成します。今回は cluster(バージョン番号) というデータベースクラスタ名にします。

```bash
$ cd $HOME/pgsql/postgresql-9.6/bin
$ ./initdb $HOME/data/cluster9_6
$ cd $HOME/pgsql/postgresql-10/bin
$ ./initdb $HOME/data/cluster10
$ cd $HOME/pgsql/postgresql-11/bin
$ ./initdb $HOME/data/cluster11
$ cd $HOME/pgsql/postgresql-12/bin
$ ./initdb $HOME/data/cluster12
$ cd $HOME/pgsql/postgresql-13/bin
$ ./initdb $HOME/data/cluster13
$ cd $HOME/pgsql/postgresql-14/bin
$ ./initdb $HOME/data/cluster14
```

# 各種スクリプトの作成
まず、以下のようなバージョンとPostgreSQLの実行ディレクトリを設定するスクリプト(setver.sh)を作成します。VER変数にSupported Version (9.6, 10, 11, 12, 13) と Development Version (14) の6つのバージョンを設定します。

```sh:setver.sh
#!/bin/sh
VER='9.6 10 11 12 13 14'
USAGE="Usage: $0 $VER"

if [ $# != 1 ] || ! echo "$VER"|grep -q $1 ; then
  echo $USAGE
  exit 1
fi

export PG_VERSION=$1
export PG_DIR="$HOME/pgsql/postgresql-$1/bin/"
echo "Set PostgreSQL $PG_VERSION"
```

次に以下のようなPostgreSQLインスタンスの起動/確認/停止を行うスクリプト(pgctl.sh)を作成します。環境変数 PG_VERSION が設定されていない場合、DEF変数に指定されたバージョンのインスタンスを起動/確認/停止します。

```sh:pgctl.sh
#!/bin/bash

DEF="10"
USAGE="Usage: $0 {start|stop|status}"
if [ $# != 1 ]; then
  echo $USAGE
  exit 1
fi
VERSION=$PG_VERSION
if [ -z $VERSION ] ; then
  VERSION=$DEF
fi

PGCTL="$HOME/pgsql/postgresql-$VERSION/bin/pg_ctl"
PGDATA="$HOME/data/cluster$VERSION"
PGLOG="$HOME/data/cluster$VERSION/pglog$VERSION.log"

case "$1" in
  start)
    echo -n "Starting PostgreSQL $VERSION: "
    $PGCTL -D $PGDATA -l $PGLOG -w start
    touch /var/lock/pgsql
    ;;
  stop)
    echo -n "Stopping PostgreSQL $VERSION: "
    $PGCTL -D $PGDATA -m f stop
    rm -f /var/lock/pgsql
    ;;
  status)
    echo -n "postgreSQL $VERSION: "
    $PGCTL -D $PGDATA status
    ;;
  *)
    echo $USAGE
    exit 1
esac

exit 0
```

# PostgreSQLインスタンスの起動と動作確認
前述で作成しました setver.sh スクリプトで実行する PostgreSQL インスタンスを特定して、pgctl.sh スクリプトでインスタンスの起動/確認/停止を行います。

以下のように、PostgreSQL 14 を起動する PostgreSQL インスタンスとして指定します。

```bash
$ source ./setver 14
Set PostgreSQL 14
```

pgctl.sh スクリプトでインスタンスの起動します。

```bash
$ ./pgctl.sh start
Starting PostgreSQL 14: waiting for server to start.... done
server started
```

pgctl.sh スクリプトでインスタンスの状態を確認します。PostgreSQL 14 インスタンスが起動されていることが確認できます。

```bash
$ ./pgctl.sh status
postgreSQL 14: pg_ctl: server is running (PID: 9631)
/home/hoge/pgsql/postgresql-14/bin/postgres "-D" "/home/hoge/data/cluster14"
```

環境変数 $PG_DIR のディレクトリへ移動して、psql を実行します。PostgreSQLのバージョンを確認すると、PostgreSQL 14beta2 が起動していることが確認できます。
今回は postgres データベースにアクセスしましたが、別のデータベースが必要な場合は同じディレクトリにある createdb コマンドでデータベースを作成して下さい。

```bash
$ cd $PG_DIR
$ ./psql postgres
psql (14beta2)
Type "help" for help.

postgres=#
```

次に PostgreSQL 14 インスタンスを停止して、以下のように PostgreSQL 13 を起動します。psql で PostgreSQL のバージョンを確認すると、PostgreSQL 13.2 が起動していることが確認できます。

```bash
$ cd $HOME
$ ./pgctl.sh stop
Stopping PostgreSQL 14: waiting for server to shut down.... done
server stopped
$ source ./setver 13
Set PostgreSQL 13
$ ./pgctl.sh start
Starting PostgreSQL 13: waiting for server to start.... done
server started
$ cd $PG_DIR
$ ./psql postgres
psql (13.2)
Type "help" for help.

postgres=# SELECT version();
                                               version                                               
------------------------------------------------------------------------------------------------------
 PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, 64-bit
(1 row)
postgres=# \q
```

# PostgreSQL 13 を 13.2 から 13.3 へ置き換え

マイナーバージョンアップされた場合の対応方法を紹介します。まず、PostgreSQL 13.2 を停止して、アンインストールします。

```bash
$ cd $HOME
$ ./pgctl.sh stop
Stopping PostgreSQL 13: waiting for server to shut down.... done
server stopped
$ cd src/postgresql-13.2/
$ make uninstall
```

次に PostgreSQL 13.3 をインストールします。

```bash
$ cd $HOME/src
$ wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz
$ tar xvzf postgresql-14beta1.tar.gz 
$ cd work/postgresql-14beta2
$ ./configure --prefix=$HOME/work/postgresql-13
$ make
$ make install
```

以下のように PostgreSQL 13 を起動します。psql で PostgreSQL のバージョンを確認すると、PostgreSQL 13.3 が起動していることが確認できます。

```bash
$ ./pgctl.sh start
Starting PostgreSQL 13: waiting for server to start.... done
server started
$ cd $PG_DIR
$ ./psql postgres
psql (13.3)
Type "help" for help.

db13=# SELECT version();
                                               version                                               
------------------------------------------------------------------------------------------------------
 PostgreSQL 13.3 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, 64-bit
(1 row)
```

マイナーバージョンアップは、データベースクラスタ、データベースを変更なしに使用可能ですので今回は13.2で作成したデータベースクラスタ、データベースをそのまま使用しました。
ただし、PostgreSQL 14 はまだ、Development Version であることから 14beta1 から 14beta2 へバージョンアップの際には、データベースクラスタをそのまま使用することができません。データベースクラスタのアップグレードが必要になります。詳しくはこちらを参照願います。

- [PostgreSQL 14beta2 Documentation 19.6. Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/14/upgrading.html)

# まとめ

複数バージョンの PostgreSQL をインストールして、スクリプトを作成することで、使い分ける方法をまとめました。。自分のアカウントで簡単にPostgreSQLの複数バージョンのPostgreSQLを確認することができました。

もし、記述について誤りがあったり、気になることがあれば、編集リクエストやコメントでフィードバックしていただけると助かります。

# 参照

以下の情報を参考にさせて頂きました。

- [PostgreSQL: Versioning Policy](https://www.postgresql.org/support/versioning/)
- [PostgreSQL: Documentation: 13: pg_uograde](https://www.postgresql.org/docs/current/pgupgrade.html)