PlanetScale から Supabase にデータを移行した話(Prisma使用)
概要
PlanetScale が無料プランを廃止したので、 Supabase に移行しようという話です。
TL;DR
Supabase でデータベースを作って Prisma でテーブルを作成し、PGLoader を使ってデータだけを移行する話です。
準備
PGLoader のインストール
まずは移行元の PlanetScale のデータベースURLと移行先の Supabase のデータベースURLを準備します。
次に、移行をしてくれる PGLoader というソフトウェアをインストールします。 Debian 系であれば
sudo apt install pgloader
でインストールすることができます。他の OS の場合は 公式ドキュメントに書いてあるインストール方法を参考にしてください。
Prisma の設定
次に schema.prisma
の設定を変更します。 PlanetScale は MySQL だったのですが、 Supabase は PostgreSQL なので、以下のように providor
を変更します。
datasource db {
...
- providor = "mysql"
+ providor = "postgresql"
...
}
そして、データベースURLを変更するので url
の変更もします。(.env
にデータベースURLを保存している場合はそちらを変更します。)
datasource db {
...
- url = "mysql://..."
+ url = "postgresql://..."
...
}
そして、心の準備をしてください。(たまによくわからないエラーが出ます。そういうときは成功するまでコマンドを繰り返すと成功する場合があります。)
移行
では実際に移行をします。
テーブル作成
まず、 Supabase 側にテーブルを作成します。
プロジェクトのディレクトリで以下のコマンドを実行してください。
npx prisma migrate dev
データのインポート
次にデータの移行をします。
どこかに以下の内容で migration.load
というファイル(名前はなんでもいい)を作成してください。
LOAD DATABASE
FROM [pscaleDB]?sslmode=require
INTO [supabaseDB]
ALTER SCHEMA '[schema]' RENAME TO 'public' WITH QUOTE IDENTIFIERS, DATA ONLY, TRUNCATE, CREATE NO TABLES;
-
[pscaleDB]
には PlanetScale のデータベース URL を入れます。ただし、最後についている?sslaccept=strict
は消して、?sslmode=require
に置き換えてください。
こんな感じになるはずです。mysql://username:password@aws.connect.psdb.cloud/dbname?sslmode=require
-
[supabaseDB]
には Supabase のデータベース URL を入れます。
こんな感じになるはずです。postgres://postgres.xxxx:password@xxxx.pooler.supabase.com:6543/postgres
-
[schema]
には PlanetScale のデータベースの名前(プロジェクトの名前)を入れてください。 - 全体でセミコロンは一つだけです。
以上のようにファイルを作成することができたら、以下のコマンドを実行してください。
pgloader migration.load
そうすることで、自動的にデータの移行が始まります。
コマンドの実行が終了したらデータベース移行は完了です。引き続き Prisma による開発ライフを送ってください。
詳しい説明
migration.load
の中身の詳しい説明をします。うまく行かなかったときの参考などに使ってください。
LOAD DATABASE FROM [db1] TO [db2]
という構文を使うことで db1
から db2
への移行をすることができます。
デフォルトではテーブルを新しく作成し、データを入力します。ですが、これだけでは以下の問題が発生します。
- PlanetScale 側の schema と Supabase 側の schema が一致しない。
- テーブルの構造が
schema.prisma
と一致しない。 - テーブルの名前が
schema.prisma
と一致しない。(パスカルケースからスネークケースに変えられる)
なので、追加で以下のようなものを追加します。
ALTER SCHEMA '[schema]' RENAME TO 'public' WITH QUOTE IDENTIFIERS, DATA ONLY, TRUNCATE, CREATE NO TABLES
その説明はこのようになります。
-
ALTER SCHEMA '[schema]' RENAME TO 'public'
PlanetScale 側では schema はデータベースの名前で、 Supabase 側では schema はpublic
が使われるので、それの変更を行います。 -
WITH [option], [option]...
WITH
構文ではいろいろなオプションを追加できます。カンマで区切ります。-
QUOTE IDENTIFIERS
: テーブル名などをクオートします。つまり、テーブル名をそのままで維持します。 -
DATA ONLY
: 移行のときにデータのみを移行します。 -
TRUNCATE
: 一度テーブルをTRUNCATE
します。 -
CREATE NO TABLES
: 新しくテーブルを作成せずに、すでにあるテーブルを変更しないようにします。
-
※WITH
に関する細かい使用はこちらを参考にしてください。https://pgloader.readthedocs.io/en/latest/ref/mysql.html?highlight=options with#mysql-database-migration-options-with
※もしかしたらいらないものも有りますが、あっても困らないはずです。
詳しい説明は以上です。ここに書いてある説明はとてもざっくりした説明なので、もしもより詳しく理解したい場合は PGLoader のドキュメントを読んでください。
備考
PostgreSQL と MySQL は相性が悪いので、移行したあとも一度データの不整合などがないかチェックをすることをおすすめします。
まとめ
今回は PlanetScale の無料プランがなくなるということで Supabase に移行しようという記事を書きましたが、ここにたどり着くまでが非常に長かったです(約12時間)。Supabase 公式で紹介されている方法でも何故かエラーは出るし、公式以外の情報も少なく、 PGLoader の公式ドキュメントも活用していろいろな質問の回答なども参考にしてようやくこの方法にたどり着きました。なので、皆さんには同じような失敗をしないでほしいという思いでこの記事を書きました。
後日に、どのように PlanetScale のブランチ機能を用いた開発を Supabase のローカル環境を用いる開発に移行するかに関しても一つ記事を書くつもりです。
ここまで読んでくださり、本当にありがとうございました。
最後に、もし間違っている情報などが有りましたら気軽に言ってください。
参考にした記事など
Supabase 公式
ここでは
ALTER SCHEMA 'public' OWNER TO 'postgres';
set wal_buffers = '64MB', max_wal_senders = 0, statement_timeout = 0, work_mem to '2GB';
という記述が有りますが、私の場合は OWNER
のところで文法エラーが出たので参考にしないことをおすすめします。
pgloader 3.4.1でMySQLからPostgreSQLへスマートに移行しよう(翻訳)
あまり参考にしなかった記事ですが、もしかしたら最も有益な情報が乗っていたかもしれません。
StackExchange での質問
https://dba.stackexchange.com/questions/191090/how-to-use-pgloader-to-transfer-sqlite-to-postgres-with-table-name-in-uppercase#:~:text=None of your table names,column names to be lowercased.&text=PostgreSQL only takes account of,which is a typing nightmare!
私が WITH
という文法を知ったきっかけの StackExchange での質問です。
Discussion