RDS MySQL8からHeroku PostgreSQL12へデータ移行する

2020年5月29日

Heroku

前回は、Rails アプリケーションを Heroku にデプロイする方法を紹介しました。

Heroku
RailsアプリケーションをHerokuで公開する

前回は Rails の開発環境を Docker で作成しました。 作成した Rails のアプリケーションを Herok ...

続きを見る

今回は Amazon RDS MySQL8 から Heroku PostgreSQL12 へ csv 形式でデータを移したときのメモです。この記事に出てくる heroku コマンドのインストール方法やログイン方法は前回の記事で解説をしているので、設定がまだの方は上のリンクから前回の記事を確認してください。

目次

  1. RDS MySQL からデータを csv 形式でエクスポートする
  2. csv を PostgreSQL にインポートする
  3. SEQUENCE を設定する
  4. Heroku のドキュメントでは pgloader が紹介されていた

RDS MySQL からデータを csv 形式でエクスポートする

RDS からデータを csv 形式でエクスポートします。RDS は SELECT ... INTO OUTFILE が使えないので、mysql コマンドの -e オプションで SELECT 文を実行し、結果を sed コマンドで CSV 形式に整形しつつファイルに出力しました。

mysql -u ${user} -p -h ${host} ${dababase} -e "SELECT * FROM users" | sed -e 's/^/"/g' | sed -e 's/$/"/g' | sed -e 's/\t/","/g' | sed -e 's/"NULL"//g' > users.csv

私のデータは単純だったのでこれで大丈夫でしたが、データの中にダブルクオーテーションやタブが含まれている場合はエスケープするなど工夫が必要だと思います。またこの後、PostgreSQL の COPY コマンドでデータをインポートするために、NULL を空欄に置換しています。

csv を PostgreSQL にインポートする

MySQL から出力した csv のインポートには PostgreSQL12 の COPY コマンドを使って、標準入力からインポートしました。

cat users.csv | psql $(heroku config:get DATABASE_URL --app ${app_name}) -c "COPY users FROM STDIN WITH (FORMAT csv, HEADER true);"

PostgreSQL12 の COPY コマンドを csv フォーマットで利用する際のデフォルト値は以下の通り。これに合わせてデータを出力するとスムーズに取り込めます。

  • DELIMITER(列の区切り文字)はカンマ
  • QUOTE(囲み文字)ダブルクオーテーション
  • NULL は引用符のない空文字

詳しくはPostgreSQL 12.0文書 COPYを参照。

SEQUENCE を設定する

MySQL のときは id 列に auto_increment を設定することが多いと思います。PostgreSQL12 の COPY コマンドでデータを移した場合、id 列の SEQUENCE に手動で反映する必要がありました。

PostgreSQL 12.0文書 9.16. シーケンス操作関数

こんなテーブルがある場合

myapp::DATABASE=> \d users;

Table "public.users"
         Column         |              Type              | Collation | Nullable |                 Default
------------------------+--------------------------------+-----------+----------+-----------------------------------------
 id                     | bigint                         |           | not null | nextval('users_id_seq'::regclass)
 email                  | character varying              |           | not null | ''::character varying
 password               | character varying              |           | not null | ''::character varying
 created_at             | timestamp(6) without time zone |           | not null |
 updated_at             | timestamp(6) without time zone |           | not null |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "index_users_on_email" UNIQUE, btree (email)

id の最大値を調べて

SELECT max(id) FROM users;

setval で最大値を設定します。

SELECT setval('users_id_seq', 100, true);

これで移行後も id の連番が維持されます。

Heroku のドキュメントでは pgloader が紹介されていた

Heroku のドキュメントでは pgloader を使った方法が紹介されています。今回は csv で移行できたので使いませんでしたが、ドキュメントのリンクを残しておきます。

Migrating from MySQL to Postgres on Heroku | Heroku Dev Center

おわりに

3 回にわたって紹介してきた Rails アプリを Heroku で動作させる方法はこれで終わりです。最初から確認したい方は以下からどうぞ。

Rails
Alpine+Rails6+PostgreSQLのDockerfileを作る

Alpine Linux ベースの Docker イメージで Rails6.1 + PostgreSQL の環境を作る機 ...

続きを見る

-技術ブログ
-