PlanetScaleは、2024年4月8日に無料枠を廃止します。
そのため、私はとあるWebサービスのDBをPlanetScaleからSupabaseに移行することにしました。
Supabaseは、無料で利用することもできるPostgreSQLベースのDBです。
Supabaseは既に利用したことがあり、今回選定しました。大変使いやすく、またphpMyAdminのようにWeb上でデータを直接編集できるところも便利でおすすめです。
移行手順
今回は少量のデータだったため試していませんが、大量のデータがある場合はpgloaderを使うほうが良いかもしれません。
前提として、今回移行するサービスは、以下の記事に書かれたような構成で作られています。
DBとしてPlanetScaleを利用し、ORMとしてPrismaを利用しています。
Supabaseのテーブル作成
SupabaseとPrismaを接続します。Prismaでスキーマが定義されているため、接続するだけで自動的にDBの準備は完了します。
SupabaseでPrismaを使う方法は、下記の公式ドキュメントに詳しく書かれています。
重要な部分は、.env
でDATABASE_URLの他にDIRECT_URLが必要になる点、そしてDATABASE_URLの末尾には?pgbouncer=true
が必要な点です。
Supabaseは、PostgreSQLの接続にあたりコネクションプーリング機能を利用しています。これは、接続や切断を繰り返した際にメモリが枯渇したり性能が劣化したりするのを防ぐ機能です。
Supabaseではこの機能のために、Session modeとTransaction modeという2種類の接続先が用意されており、操作の性質によって接続先を変えることでパフォーマンスが最大化できるようになっています。
モード毎の接続先は、Supabaseの「Project Settings」ページから「Database Settings」を開き、ページ最上部の「Connection string」という項目でそれぞれ確認できます。
.env
のDATABASE_URLにはTransaction modeの接続先を、DIRECT_URLにはSession modeの接続先を指定してください。指定の際に、DATABASE_URLの末尾に?pgbouncer=true
を追加するのを忘れないようにしてください。
URLは、パスワードの部分のみ[YOUR-PASSWORD]
となっていますので作成時に指定したDBのパスワードで置き換えてください。
続いて、schema.prisma
を以下のように置き換えてください。
datasource db {
- provider = "mysql"
- url = env("DATABASE_URL")
- relationMode = "prisma"
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
}
ここまでできたら、ターミナルでprisma db push
すればDBテーブルが作成できるはずです。
PlanetScaleのデータをエクスポート
GUIからエクスポートすることは現状できないので、PlanetScale公式のCLIであるpscaleを利用します。
ターミナルでpscale auth login
してからpscale database dump [database] [branch]
します。branch名はだいたいmain
だと思います。
すると、カレントディレクトリにpscale_dump_*
で始まるディレクトリが作成され、その中にsql形式のファイルが出力されます。
*-schema.sql
みたいなファイルにスキーマが定義されており、*.00001.sql
みたいなファイルにデータが定義されています。前者は使わないです。
Supabaseにデータをインポート
いかにもそのままインポートに使えそうなSQLが生成されましたが、MySQLとPostgreSQLでクォーテーションの扱いが異なるため、そのままでは使えません。
「"」を「'」に、「`」を「"」に、「\'
」を「''」に変換する必要があります。
簡単なやり方として、VSCodeの検索機能でファイルを絞り込んで置換する方法があります。
「含めるファイル」に*00001.sql
を指定し、すべて置換を実行すると置き換えることができます。
この方法では、元の文字列にダブルクォーテーションが含まれている場合などに、データが破損する可能性があります。データの性質に合わせて、適宜やり方を変更してください。
置き換えることができたら、SupabaseのSQL EditorにSQLを貼り付けて実行していきましょう。
なお、よく出るエラーとして、外部キー制約によるエラー、真偽値が数値で書かれていることによるエラーがあります。
外部キー制約によるエラー
ERROR: 23503: insert or update on table "*" violates foreign key constraint "*"
一時的に無効化できるようです。
真偽値が数値で書かれていることによるエラー
ERROR: 42804: column "*" is of type boolean but expression is of type integer
こちらは例えば「0」を「'0'」に置き換えることで、PostgreSQLに真偽値だと解釈させることができます。
まあ大体「Debug with Supabase AI」でなんとかなります。