0
0

More than 1 year has passed since last update.

Prismaを活用したマイグレーション・ロールバックSQLの作成 DB構築→モデル作成をやっている人向け

Posted at

はじめに

基本的なORMの利用方法としては、以下のようにモデル→データベースの順番で作成・構築していくと思う。

  1. モデルを定義
  2. データベースにそのモデルに合致するテーブルを構築

ただ、モデルの定義をしてからテーブルを構築だとどうしてもかゆい所に手が届かなかったりもするので、上記の逆の手順で、データベース→モデルという順番で作成・構築する事もあると思う。

  1. GUIツール(MySQL WorkbenchやNavicatなど)を利用してテーブルを設計
  2. テーブル定義からモデルを作成

ただこの場合、ORMライブラリに備わっている機能を使ってモデルの変更に合わせマイグレーションをするという事ができないので、dev, staging, productionと環境があった時には、手動でSQLを流してマイグレーションを行う必要がある(モデル→テーブルの変更の順であれば、Prismaの場合、prisma migrate deployで開発環境で作成したマイグレーションを環境ごとに適用するだけ(詳細はここを参照)。

そのマイグレーションのSQLとロールバックのSQLを、うまく簡単に作り、バージョン管理もできなかな~と思い、今回はPrismaを利用して、手動でマイグレーション・ロールバックのSQLを作成する手順を考えてみたいと思う。

データベースへの更新、モデルへの反映、マイグレーション用のSQL作成の流れ

まず、初期化と変更の2つがあると思うので、2つに分けてみていく。

  • 初期化
    一番最初にテーブルを作成するタイミングで、マイグレーションの初期ファイルを作る
  • 変更
    テーブルの追加・変更など繰り返し行う手順で、今回で言うとこの変更時のマイグレーション・ロールバックのSQLを作成する部分が肝になる

初回

初回はIntrospectionにあるように、データベースからテーブルの定義を読み出し、モデルを作成したり、マイグレーションの初期ファイルを作成する。手順化すると以下のようになるだろう。

  1. GUI(MySQL WorkbenchやNavicat)でテーブルを設計・作成
  2. npx prisma db pullでモデルを作成
  3. mkdir -p prisma/migrations/0_initで初期状態を作るマイグレーションの格納先を作成
  4. npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sqlで初期状態を作るマイグレーションのSQLを作成

実際にやってみた時のログは以下。

変更

続いて、今回やりたかったことの本題になる、テーブルの追加・変更を行った時に、各環境に反映するためのマイグレーションのSQLをどうやって作成するか、またロールバックのSQLをどうやって作成するか、を見ていきたいと思う。手順のサマリとしては以下のようになる。

  1. GUI(MySQL WorkbenchやNavicat)でテーブルを設計・作成
  2. mkdir -p prisma/migrations/1_hogehogeでマイグレーションの格納先を作成
  3. npx prisma migrate diff --from-schema-datamodel prisma/schema.prisma --to-url mysql://root:@localhost:3306/prisma-express --script > prisma/migrations/1_hogehoge/migration.sqlでマイグレーションのSQLを作成する(詳細はのちほど)
  4. npx prisma migrate diff --from-url mysql://root:@localhost:3306/prisma-express --toschema-datamodel prisma/schema.prisma script > prisma/migrations/1_hogehoge/rollback.sqlでマイグレーションのSQLを作成する(詳細はのちほど)
  5. npx prisma db pullでモデルを更新

少し補足する。

4,5の手順だが、それぞれ以下のように考えてマイグレーション・ロールバックのSQLを作成している。

  • 4
    データベースのテーブルが最新で、手元のモデルはそれを反映していないので、手元のモデル→データベースのテーブルに同期するために必要なSQLを出力すると、それが各環境に適用すべきマイグレーションのSQLになる
    そのため、--from-schema-datamodelでローカルのモデルを指定し、--to-urlでデータベース(のURL)を措定している
  • 5
    こちらは4の逆の考えでロールバックのSQLを作成している
    つまり、データベースのテーブルが最新なので、その最新の状態を手元のモデルに反映する(データベースのテーブル→モデル)をするために必要なSQLを出力すると、 それがロールバックのSQLになる
    そのため、--from-urlでデータベース(のURL)を指定し、--to-schema-datamodelでローカルのモデルを措定している

実際にやってみた時のログは以下。

※ただ、上記の方法で課題がある。prisma migrate diffで--scriptオプションを付与して生成されるSQLのCOLLATEがutf8mb4_unicode_ciになってしまい、データベースのテーブルの状態と乖離してしまう
現時点でissueを見る限り、この部分は手動で修正が必要になる。

※上記のPrismaの動きに関して、MySQL8のデフォルトのCOLLATEはutf8mb4_0900_as_ciであるにもかかわらず、Prismaで作成したSQLのCOLLATEがなぜutf8mb4_unicode_ciになるのかは謎・・・。どこからきているのか?不明だった(MySQL8のデフォルトのCollationについてはここを参照)。
image.png

まとめとして

Prismaを活用する事で、データベース→モデルという逆の順番で開発を進めていても、効率よくマイグレーション・ロールバックのSQLを作成でき、またそれをGitの管理下に置く事でリリース時にはそれを流せばいいか?という事だけ気にすればよくなるのでいいのではと思った(マイグレーション・ロールバックのSQLをリリースの準備で作らないで良くなるし、そのSQLがどこにあるか分からないという事態にもならないので)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0