Postgresのアップグレードでロケールが一致しない場合の対処法

Postgresのアップグレードでロケールが一致しない場合の対処法 プログラミング
Postgresのアップグレードでロケールが一致しない場合の対処法

Postgresのアップグレードでロケールが一致しない場合ってありますよね。

旧DBでは「en_GB.UTF-8」だったのに、新DBでは「jp_GB.UTF-8」で、新DBに合わせたい時。

そんな時の対処法をご説明致します。

本記事ではPostgres9.6からPostgres10へのアップグレードを元に説明させて頂きます。

このブログは現役のエンジニア(プログラマー歴が約12年)の僕(よしたか)が2019年12月後半から日々更新しております。

もしもアフィリエイトは会員登録後も無料です!
今すぐ会員登録してアフィリエイトを始めよう!

pg_upgradeコマンドでロケールが一致しない例

「pg_upgrade」コマンドでPostgresのアップグレードを行う場合、

$ /usr/pgsql-10/bin/pg_upgrade --old-bindir=/usr/pgsql-9.6/bin --new-bindir=/usr/pgsql-10/bin --old-datadir=/var/lib/pgsql/9.6/data --new-datadir=/var/lib/pgsql/10/data --jobs=6 --check
整合性チェックを実行しています。
-----------------------------
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 invalid "unknown" user columns                 ok
Checking for hash indexes                                   ok

データベース"postgres"の lc_collate 値が一致しません:旧 "en_GB.UTF-8"、新 "ja_JP.UTF-8"
失敗しました、終了しています
$ psql

こんな感じで「--check」オプションを付けると、移行可能かのみ確認する事が出来ますが、上記のようにロケールのエラーが出る場合があります。

旧DBと新DBのロケールの確認

実際に旧DBと新DBのロケールを確認してみると、

postgres=# select name,setting,context from pg_settings where name like 'lc%';
    name     |   setting   |  context
-------------+-------------+-----------
 lc_collate  | en_GB.UTF-8 | internal
 lc_ctype    | en_GB.UTF-8 | internal
 lc_messages | en_GB.UTF-8 | superuser
 lc_monetary | en_GB.UTF-8 | user
 lc_numeric  | en_GB.UTF-8 | user
 lc_time     | en_GB.UTF-8 | user
(6 行)

postgres=#
postgres=# select name,setting,context from pg_settings where name like 'lc%';
    name     |   setting   |  context
-------------+-------------+-----------
 lc_collate  | jp_GB.UTF-8 | internal
 lc_ctype    | jp_GB.UTF-8 | internal
 lc_messages | jp_GB.UTF-8 | superuser
 lc_monetary | jp_GB.UTF-8 | user
 lc_numeric  | jp_GB.UTF-8 | user
 lc_time     | jp_GB.UTF-8 | user
(6 行)

postgres=#

このように確かに違ってますね。

既存DBのロケールを新DBのロケールに合わせる

では実際に既存DBのロケールを新DBのロケールに合わせてみましょう。

// 事前バックアップ
$ pg_dumpall > backup.sql

// 既存ディレクトリをバックアップ
$ mv /var/lib/pgsql/9.6 /var/lib/pgsql/9.6_org

// initdbでロケールを指定してデータベースを再作成
$ initdb --locale=ja_JP.UTF-8 -D /var/lib/pgsql/9.6/data

// 事前バックアップからデータ復元
$ psql -f backup.sql postgres

// 後はPostgresを起動してロケールの確認

このような感じで、ロケールの変更にはinitdbを行う必要があります。

後は改めて「pg_upgrade」コマンドを使ってアップグレードを行えばOKかと。

1回バックアップを取って、再度データベースを作って…と手間がかかるかもしれませんが、一番確実な方法かなと思います。

まとめ

この記事のおさらい
  • Postgresのアップグレードではロケールを合わせよう
  • Postgresのアップグレードは「pg_upgrade」を使おう

いかがだったでしょうか。

こういった場面になっても混乱せず、1つ1つ対処していきたいですね。

今日はさくっとここまでとなります!