Herokuの無償プラン廃止に伴い、Flyへのアプリケーション移行をしていたところ、データベースの転送でエラーが発生しました。
対処法をまとめます。
移行手順
Herokuからの移行について、Flyから公式のドキュメントが用意されているので、これを参考に移行しました。
https://fly.io/docs/rails/getting-started/migrate-from-heroku/
発生したエラー
Transfer the Database の pg_dump
を実行したところで以下のようなエラーが出ました。
# pg_dump -Fc --no-acl --no-owner -d $HEROKU_DATABASE_URL | pg_restore --verbose --clean --no-acl --no-owner -d $DATABASE_URL
pg_dump: error: server version: 14.7 (Ubuntu 14.7-1.pgdg20.04+1); pg_dump version: 13.9 (Debian 13.9-0+deb11u1)
pg_dump: error: aborting because of server version mismatch
pg_restore: error: input file is too short (read 0, expected 5)
エラーの原因
「AppサーバーにインストールされているPostgreSQL Clientのバージョン」と「Herokuで動いているPostgreSQL Serverのバージョン」が一致していないためです。
FlyのAppサーバーにインストールされているPostgreSQL Clientのバージョンは 13.9
です。
$ fly ssh console
# pg_dump --version
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
pg_dump (PostgreSQL) 13.9 (Debian 13.9-0+deb11u1)
Herokuで動いているPostgreSQL Serverのバージョンは 14.7
です。
$ heroku pg:info
Plan: Mini
Status: Available
Connections: 0/20
PG Version: 14.7
Created: 2019-02-19 13:56 UTC
Data Size: 14.9 MB/1.00 GB (In compliance)
Tables: 5
Rows: 5776/10000 (In compliance)
Fork/Follow: Unsupported
Rollback: Unsupported
Continuous Protection: Off
Add-on: postgresql-parallel-80887
エラーとは直接関係ありませんが、Flyで動いているPostgreSQL Serverのバージョンは 15.2
でした。ややこしい。。。
$ fly pg connect --app (FlyのApp名)-db
# SELECT version();
version
--------------------------------------------------------------------------------
---------------------------------------------
PostgreSQL 15.2 (Debian 15.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by g
cc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
(1 row)
対処法
本来は上記のバージョンを全て揃えるのが理想ですが、今回はバージョンの差分自体には目を瞑り、エラーを回避しつつデータベース転送することにしました。
まず、HerokuのDBをbackupします。
$ heroku pg:backups:capture --app (HerokuのApp名)
$ heroku pg:backups:download --app (HerokuのApp名)
ダウンロードした latest.dump
をAppサーバーに転送します。
$ flyctl sftp shell
# put latest.dump
転送が完了したら、Appサーバーのコンソールに入り、restoreします。
$ fly ssh console
# pg_restore --verbose --clean --no-acl --no-owner -d $DATABASE_URL latest.dump
これで、データベースの転送が完了しています。