RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

イベント詳細についてはこちらをクリック

【PostgreSQL 9.4 → 11】pg_upgradeでデータベースクラスタをバージョンアップ

こんにちは
楽楽明細開発課のsts-250rrです。

先日Postgres11の入った検証環境に、現在運用中の環境のデータを移行して検証したいという機会がありました。

何点か意外とあるんじゃないかなというポイントがありましたので、Try&Errorの内容をまとめておこうと思います。

※本記事内でのコマンドはDockerコンテナで作業をイメージしたコマンドを実施しています。 f:id:sts-250rr:20190826191831p:plain

やったこと

ポイント・イン・タイム・リカバリ (PITR)の方法でデータベースクラスタ(/var/lib/pgsql/data)とアーカイブログ(/var/lib/pgsql/data/pg_xlog/)を使って、検証環境にリストアして復元をしようとしました。

ところですっかり忘れていたのですが、現在運用中のデータベースはPostgres9.4なのです。

PostgreSQLはメジャーバージョン間ではデータベースクラスタの互換性がないため、Postgres11のサーバを起動しようとした時にバージョン不一致でエラーになります。

[root@12d698375565 ~]# service postgresql-11 start

An old version of the database format was found.
You need to upgrade the data format before using PostgreSQL.
See (Your System's documentation directory)/postgresql-11.5/README.rpm-dist for more information.
[root@12d698375565 ~]# 

ここからTry&Errorのスタートです。

Try&Error:データベースクラスタをバージョンアップする

上述の通りエラーの内容は明白で、移行元と移行先のデータベースのバージョンが不一致であるため、 データベースクラスタをバージョンアップすれば良いというわけです。 いくつか方法があるようですが、pg_upgradeでやると簡単そうということまでわかりました。

ただ用語としてpg_upgradeと聞いたことがあっても使ったことはありませんでした。 Tryしていきます。

Try:pg_upgradeはどう使ってやればよいのか

困った時は公式のドキュメントを確認です。
実行コマンドはこんな感じ

pg_upgrade -b oldbindir -B newbindir -d olddatadir -D newdatadir [option...]

どうやらpg_upgradeを使うためには移行元と移行先のPostgresのインストールディレクトリと/dataのディレクトリが必要なようです。

検証環境側に必要なものはそろっているのでしょうか?

[root@12d698375565 ~]# ls /usr/pgsql-9.4
ls: cannot access /usr/pgsql-9.4: No such file or directory
[root@12d698375565 ~]# 

・・・・。

ERROR:存在しないPostgres9.4

速やかにインストールします。 (Postgresインストールの詳細については割愛します。)

[root@12d698375565 ~]# yum -y install postgresql94-server
・・・
Complete!
[root@12d698375565 ~]# service postgresql-9.4 initdb
Initializing database:                                     [  OK  ]
[root@12d698375565 ~]# 

念の為、運用中のデータを移行して、9.4の状態でDBを確認しておきます。

[root@12d698375565 ~]# service postgresql-9.4 start
Starting postgresql-9.4 service:                           [  OK  ]
[root@12d698375565 ~]# su - postgres
-bash-4.1$ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 pg94      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)

-bash-4.1$

9.4の状態で起動でき、中身も確認できました。

改めて、pg_upgradeに必要な資材があるかを確認して、

[root@12d698375565 ~]# ls /usr/pgsql-9.4
bin  lib  share
[root@12d698375565 ~]# ls /var/lib/pgsql/9.4/data
base         pg_hba.conf    pg_multixact  pg_snapshots  pg_tblspc    postgresql.auto.conf
global       pg_ident.conf  pg_notify     pg_stat       pg_twophase  postgresql.conf
pg_clog      pg_log         pg_replslot   pg_stat_tmp   PG_VERSION
pg_dynshmem  pg_logical     pg_serial     pg_subtrans   pg_xlog
[root@12d698375565 ~]# ls /usr/pgsql-11
bin  lib  share
[root@12d698375565 ~]# ls /var/lib/pgsql/11/data
base              pg_hba.conf    pg_serial     pg_twophase           postmaster.opts
current_logfiles  pg_ident.conf  pg_snapshots  PG_VERSION            postmaster.pid
global            pg_logical     pg_stat       pg_wal
log               pg_multixact   pg_stat_tmp   pg_xact
pg_commit_ts      pg_notify      pg_subtrans   postgresql.auto.conf
pg_dynshmem       pg_replslot    pg_tblspc     postgresql.conf
[root@12d698375565 ~]# 

準備完了です。

Try:pg_upgradeで11にバージョンアップ

満を辞してpg_upgradeを実行していきたいところですが、ドキュメントを見るといくつか下準備が必要なようです。

  • 新しいPostgreSQLクラスタを初期化
    • 11側のdataが更新されていると移行に失敗してしまいます。initdbで初期化しておきます。
  • 認証の調整
    • pg_upgradeは古いサーバと新しいサーバに複数回接続するためパスを要求されることがあるようです。 pg_hba.confを適切に設定しときましょう。(今回はtrustにしています。)
  • 両サーバの停止
    • 停止します。
[root@12d698375565 ~]# service postgresql-9.4 stop
Stopping postgresql-9.4 service:                           [  OK  ]
[root@12d698375565 ~]# service postgresql-11 stop
Stopping postgresql-11 service:                            [  OK  ]
[root@12d698375565 ~]# 

下準備も完了です。 11のpg_upgradeコマンドでいざ実行。

[root@12d698375565 ~]# /usr/pgsql-11/bin/pg_upgrade pg_upgrade -b /usr/pgsql-9.4/bin/ -B /usr/pgsql-11/bin/ -d /var/lib/pgsql/9.4/data/ -D /var/lib/pgsql/11/data/

pg_upgrade: cannot be run as root
Failure, exiting
[root@12d698375565 ~]# 

ERROR:postgresユーザで実行しなければならない

rootでは実行できませんでした。。。
(ドキュメントにしっかり書いてありました)

気を取り直してpostgresユーザで実行。

[root@12d698375565 ~]# su - postgres
-bash-4.1$ /usr/pgsql-11/bin/pg_upgrade pg_upgrade -b /usr/pgsql-9.4/bin/ -B /usr/pgsql-11/bin/ -d /var/lib/pgsql/9.4/data/ -D /var/lib/pgsql/11/data/
Performing Consistency Checks
-----------------------------
Checking cluster versions                                   ok
Checking database user is the install user                  ok
Checking database connection settings   
・・・
Upgrade Complete
----------------

無事成功しました。 Postgres11で起動して確認して完了です。

[root@12d698375565 ~]# service postgresql-11 start
Starting postgresql-11 service:                            [  OK  ]
[root@12d698375565 ~]# su - postgres
-bash-4.1$ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 pg94      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres+
           |          |          |             |             | =c/postgres
(4 rows)

-bash-4.1$ 

9.4のDBが11からもしっかり見えています。 やっと本筋の検証が進められそうです。

まとめ

今回やったことは旧バージョンをインストールするという手順がありましたが、 基本的にはpg_upgradeを実施しただけです。

それでも個人的には良い勉強になった事象でしたし、 次期バージョンでDBをアップデートするけど検証したいデータはまだ古い。 ということは今後も発生しそうなので、記事にしてみました。

何かの参考になれば幸いです。

Copyright © RAKUS Co., Ltd. All rights reserved.