Closed7

Atlas + Prisma(TypedSQL) によるデータベースまわりの検証

ぱんだぱんだ

この記事の方と同じ気持ち

https://zenn.dev/hokaccha/articles/496e31f8ac3387

できたらsqlcが使いたいがTSではまだ使いたくない。Prismaがいいのはわかったけどsqlcみたいに生のsqlが書きたい。というかORM特有のクエリの組み立て方が覚えられないし、あんまり覚えたくない。

そこでTypedSQL。sqlcと同じ体験がPrismaでも味わえる。また、簡単なクエリや動的クエリはsqlcだと少しめんどくさいのでそこはPrismaのORMな部分で楽に書ける。まさに美味しいところどり

TypedSQLがでたことでPrismaでいいじゃんになってきた

ちなみにTSにおけるsqlcの紹介は以下の記事を参照

https://zenn.dev/shiguredo/articles/sqlc-gen-typescript

ぱんだぱんだ

マイグレーションは?

前からタイムスタンプによるバージョンファイルを使ったマイグレーションがあまり気に入っていない。Fly wayとか。マイグレーションツールが必要なのはわかっている。

そこで見つけたのがAtlas。

https://zenn.dev/jy8752/articles/f9fda2379b57f5

従来型のマイグレーションをバージョン型マイグレーションとしてその対比となる宣言的マイグレーションを可能としている。宣言的マイグレーションはマイグレーションファイルを作成しない。そのため、従来のバージョン型マイグレーションでよく起こっていたマイグレーションファイルのコンフリクトやマイグレーション失敗時の復旧といっためんどくさいことから解放される。

これを可能としているのは高度な自動マイグレーションの仕組みでスキーマから実行すべきSQLをAtlasが自動で判断して発行する。これは本当にいい感じにSQLを発行するそうで、公式ドキュメントではsqlite3のデフォルト値の変更の例が記載されていた。(sqliteではデフォルト値の変更はできないそうなので一旦テーブルをドロップして新しく作成する必要があるそうだがそれを安全におこなうSQLを発行してくれる。)

それはスキーマという理想の状態を定義してその状態に近づけるという宣言的なスタイルはk8sやTerraformの設計と近いものを感じる。実際DBにおけるTerraformみたいなワードが公式のドキュメントでも登場する。

このマイグレーションファイルを必要としない宣言的マイグレーションのスタイルは次世代のモダンなマイグレーションスタイルと言ってもおかしくはないだろう。

また、Atlasはインフラとアプリケーションの分離みたいなこともかなり意識しているっぽくて、アプリケーション側はスキーマを編集することでDBのあるべき状態を最新の状態に保つことを責務とし、インフラエンジニアはそれを環境に反映するのが責務とすることでアプリケーションエンジニアは自分の仕事に専念できる。

他にもCIによるスキーマのチェックやプランニングの仕組みなどもあり、Cloudサービスとしての機能も多く存在する。

なのでAtlasはかなり高機能な方なため大規模な組織、開発で力を発揮するようにも感じるが宣言的マイグレーションの部分だけで採用するメリットはあると思っているので全然小規模なチームでも採用してもいいだろう。

ちなみに、国内でのAtlasの採用事例。

https://tech-blog.rakus.co.jp/entry/20250526/dbmigration

https://techblog.tver.co.jp/entry/m-kobayashi/declarative-migration-with-atlas

https://speakerdeck.com/sgash708/atlas-wopuroziekutodao-ru-sitemitahua

まあ、あんまり多くはない

ぱんだぱんだ

Prisma + Atlas

で、このAtlasをPrismaと使う方法を探すために公式ドキュメントを見ていたら、ORMサポートのページに普通にPrismaの記載があった。なんてこった

似たようなことをしようとしている記事があったが、AtlasとPrismaでスキーマをそれぞれ管理しようとしている感じだった

https://zenn.dev/otakakot/articles/85e3620bcd2daa

たぶん、少し古いのでまだORMサポートしてなかったんじゃなかろうか?わからんけど、今ならPrismaのスキーマをAtlasで扱える

https://atlasgo.io/guides/orms/prisma/getting-started

ちなみに、Prismaにもマイグレーション機能はそなわっていて、Atlasと同じように自動でスキーマからマイグレーションを生成してくれるので従来型のバージョン管理ではあるが体験はけっこういいと思ってる。さらに、Prismaにはprisma db pushする方法とprisma migrate deployする方法の2種類ある、たぶん。

prisma db pushの方はスキーマの状態をDBに反映する方法でマイグレーションファイルを生成しない。prisma migrate deployの方はマイグレーションファイルを適用する。また、マイグレーションファイルの生成にはprisma migrate diffを使う。

ここで疑問に思うのがprisma db pushって宣言的マイグレーションじゃないの?ということ。だったらAtlasいらなくない?

これはPrisma初心者すぎて混乱したのだがprisma db pushは開発用というかサッとDBの反映したいときに使うコマンドでデータの損失の可能性などがあるため本番環境では使用しないものらしい。

なるほど。

ぱんだぱんだ

Atlasを使用するメリット

Atlasを使うことでprisma db pushで実現していたような宣言的マイグレーションを本番環境でも利用することができる。が、それだけではない。PrismaとAtlasを組み合わせて使うことのメリットは以下のような感じ。

  • 本番環境でもマイグレーションファイルを作成しない、宣言的マイグレーションが可能
  • 宣言的マイグレーションでも従来型のバージョン管理にしてもAtlasを使えばマイグレーションのコンフリクトによるエラーを事前に防ぐことができる
  • 自動マイグレーション
    • Prismaのマイグレーションは自動マイグレーションなためこのメリットはないが、他のORMでは嬉しいはず
  • トリガー、ストアドプロシージャ、Postgresの拡張機能といった高度な機能も管理することができる
  • プラットフォームの構築
    • 言語やフレームワークに依存しない、マイグレーションの仕組みを整備できる。またk8sやArgoといったマイクロサービス基盤との統合やCI環境でのlint整備などを可能とする
    • 大規模組織でこういったプラットフォームチームが存在する場合はメリットとなりそう

公式ドキュメントに記載のあるORMがなぜマイグレーションツールを内臓しているかの説明が面白かったので訳を記載。

ORMの主な役割は、データベースの詳細を抽象化し、PostgreSQL、MySQL、SQL Serverなど異なるデータベース間で可能な限り同等の操作体験を提供することです(例:これらのデータベースでほぼ同じように動作すること)。抽象化レイヤーとして、ORMはテーブル、インデックス、カラムといったデータベースの共通機能に焦点を当てる傾向があり、特定のデータベース固有の高度な機能にはあまり対応していません。

私たち自身、ORMのメンテナンスに携わっている立場として(Atlas開発チームはEntのメンテナンスも行っています)、ORMの著者としての立場から断言できますが、 移行処理は「やむを得ない不便な要素」と見なされており、確かに提供は必要ですが、本質的には面倒な要件に過ぎません。 ORMはコードとデータベースの橋渡し役として機能するもので、CI/CDパイプラインやリソース管理の範疇ではなく、実行時処理を担うツールです。

このため、ORMに付属するマイグレーションツールは基本的な機能に限定されており、このような用途に適しています。より高度なスキーマ管理プロセスが必要なプロジェクトでは、Atlasのような専用ツールの使用を検討する価値があります。

AtlasのチームがEntのメンテナンスしてるの説得力ありすぎる。

上記Atlasを採用するメリットを列挙したが宣言的マイグレーション管理と高度なDB機能のサポートが一番のメリットだろう。高度なDB機能のサポートについてだが例えばあるテーブルを削除したときに削除済みテーブルにインサートしたいのでトリガーを作成するとしよう。そのトリガーはどこで管理するのだろうか?Prismaの機能ではトリガーを管理するための機能が存在しないので直接実行するしかない。しかし、Atlasを使うことでトリガーの適用も宣言的にマイグレーション管理することができる。素晴らしい!

ぱんだぱんだ

Prismaのマイグレーション

だいぶ勘違いしてた。
従来型のマイグレーションツールはタイムスタンプで管理していて既に適用済みのマイグレーションファイルより古い未適用のマイグレーションファイルがあると適用に失敗することが多い。そのため、チーム開発をしているとこのような状態になりやすくマイグレーションが失敗してしまうので手作業で解決する必要があり、面倒。

そもそも、従来型のマイグレーションは手動でマイグレーションスクリプトを書く必要があるのと、upとdown両方書かないといけないのも面倒だった。

Atlasを導入することにより上記の面倒がなくなる、素晴らしい。

しかし、Prismaのマイグレーションの仕組みも素晴らしくAtlasのように宣言的マイグレーションではないがマイグレーションの適用をタイムスタンプではなく履歴テーブルで管理しているので適用済みのマイグレーションよりも古いマイグレーションも適用できるようになっている。

さらに、Prismaのスキーマから自動でマイグレーションファイルを作成するので自分で書く必要がない。また、 Prismaの場合、ダウンマイグレーションは作成されない。

Prismaも従来型のマイグレーションツール同様、タイムスタンプで管理しているのかと思っていたがそんなことはなかった。なので、Prismaの組み込みのマイグレーションツールは十分優秀なためAtlasをわざわざ導入しなくても十分ではある。そもそも、マイグレーションファイルが作成されはするものの、Prismaのスキーマをあるべき姿にすることで、あとは自動マイグレーションでファイルが勝手に作成されていい感じに適用してくれるのはAtlasの宣言的マイグレーションとあんまり変わらない、もはや宣言的マイグレーションと言っても良いだろう。

とはいえ、Prismaのマイグレーション機能だけでは実現できないこともあるだろうからAtlasを導入するメリットはまだあるはず。

Atlasのマイグレーションはatlas.sumというファイルが生成され、競合する場合、必ず最新のブランチの状態を取り込まないといけなくなっているのでいくらか安全なのかもしれない。

ぱんだぱんだ

AtlasのProプラン

そもそも、トリガーやRLSといった高度なDBの機能をサポートするにはAtlasのProプランの契約が必要となっている。基本的な機能だけであれば無料で十分だが、ちょっと高度なことをしようとするとだいたいProプランの契約が必要となってくる。

んーーー、Atlasいらんか、、

ぱんだぱんだ

結論

PrismaやDrizzleといったORMに付属のマイグレーション機能が優秀でAtlasで実現していたような宣言的マイグレーションは実現できる。AtlasではRLSやトリガーなどの高度なDB機能をサポートしているがこれらの機能の管理にはProプラン以上の加入が必要なのでお金がかかる。その他、プラットフォームチームやインフラチームの運用に組み込みやすくk8sやArgo, CI/CD, Terraformといったツールとの統合、親和性などもあるがこれもすべての機能は無料では使えないし、大規模向けだったりエンプラ向けの話な気がする。

また、PrismaのTypedSQLもそうだしDrizzleのSQLクエリビルダーもそうだが、従来のORM的な書き方と生のSQLの2種類をサポートするのがトレンドっぽい。

なので生のSQLが書けるのはsqlcだけでは今はなくなっている。ORM的な書き方や動的クエリの書きやすさを考えるとsqlcを使うよりPrismaやDrizzleを使った方が良い気さえする。

で、Prisma, Drizzleどちらを使うにせよマイグレーション機能が十分優秀なのでAtlasはいらないだろう。

ということでPrisma, もしくはDrizzleを使っていきたい。RLSをPrismaのDSLがサポートしていないがDrizzleはサポートしているっぽいのとなんとなくDrizzleの方が機能がシンプルな気がするので個人的にはDrizzleの方が気になる。

このスクラップは23時間前にクローズされました