VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
データベースの作成
Prisma には 2 つのデータベースが必要です。アプリが使うものと、マイグレーションの計算のために内部で使う 2 つ目の「シャドウ」データベースです。両方と、それぞれに権限を持つ専用のユーザーを作成します。*.* に対してより広い CREATE/DROP 権限を付与するのではなく、前もって作成してアプリユーザーにその 1 つのデータベースへの権限を付与しておくと、パスワードが漏洩した場合の影響範囲をサーバー全体ではなく 2 つのデータベースに抑えられます。
アプリのスキャフォールド
prisma の npm の latest タグは 8.0 のリリース候補を指しています。試す分には問題ありませんが、動作し続けることを目的としたガイドのデフォルトとしては適切ではありません。
Prisma の初期化
prisma init はデフォルトで postinstall ステップを実行し、Claude Code、Cursor、Windsurf のエージェントスキルをリポジトリにスキャフォールドします (.claude/、.windsurf/、.agents/、および skills-lock.json)。--no-skills はこれをスキップします。Prisma と並行して AI コーディングエージェントを使っているなら本当に役立つ機能ですが、このガイドの範囲外です。
これにより prisma/schema.prisma、.env ファイル、および prisma7.config.ts が作成されます (Prisma 7 では設定ファイル名にバージョンのサフィックスが付きます)。接続文字列を設定します。
.env
schema.prisma に直接置いていました。Prisma 7 では、シャドウデータベースの URL を含む接続 URL は、スキーマファイルではなく prisma7.config.ts にあります。
prisma7.config.ts
schema.prisma は prisma init が作成した generator ブロックを保持し、今ではデータソースにプロバイダーのみを宣言して、接続 URL は持ちません。
prisma/schema.prisma
マイグレーションの実行
prisma/migrations/<timestamp>_init/migration.sql を生成し、prisma generate を自動で呼び出します。テーブルが存在することを確認します。
ドライバーアダプターで接続する
Prisma 7 の生成されたクライアントは、もはや自力では接続しません。引数なしのnew PrismaClient() は今では型チェックに失敗します。データベースごとに 1 つのパッケージであるドライバーアダプターを渡します。
@prisma/adapter-mariadb は MariaDB と MySQL の両方のためのアダプターです。ワイヤプロトコルが共通なので、素の MySQL に対して動作するのと同じように VillageSQL に対しても動作します。Next.js の開発モードのホットリロードがファイルを保存するたびに新しいコネクションプールを開かないように、シングルトンを設定します。
src/lib/prisma.ts
新しいアカウントへの最初の接続
MySQL 8 と VillageSQL はcaching_sha2_password プラグインでアカウントを作成します。あるアカウントが初めて認証するとき、クライアントは RSA 鍵交換を完了しなければなりません。その後はサーバーが結果をキャッシュし、以降の接続はそれをスキップする高速なパスを取ります。@prisma/adapter-mariadb は暗号化されていない接続でのその交換を拒否するため、このアカウントを一度も認証したことのないサーバーでは、ビルドが失敗します。
active=0 idle=0 はサーバーに到達できないかのように読めます。背後のドライバーのエラーのほうがより具体的です。
.env
asyncmy について記録しているのと同じ罠であり、同じ理由で断続的に起きます。mysql CLI を含め、どれかのクライアントがそのアカウントの完全な認証を一度完了すると、FLUSH PRIVILEGES またはサーバーの再起動でキャッシュがクリアされるまで、キャッシュされた結果が問題を隠します。
生成されたクライアントのインポートパスには 2 つの癖があります。index.ts がないため、@/generated/prisma (ディレクトリ) ではなく @/generated/prisma/client (ファイル) をインポートします。また、そのファイル内のすべてのエクスポートは @ts-nocheck で型付けされています。読むためではなくインポートするための生成コードだからです。
Server Component からの読み書き
src/app/page.tsx
prisma.post.findMany() は Server Component として実行されるため、一覧はクライアント側のフェッチなしに、データがすでに HTML に含まれた状態でレンダリングされます。フォームは Server Action ("use server") に送信され、同じ Prisma クライアントを通じて書き込み、revalidatePath("/") を呼び出すことで、クライアント側の更新なしに新しい投稿が表示されます。
この時点で npm run build を実行すると、実際にデータベースにクエリが発行されます。ホームページは動的 API を使っていないため、Next.js はビルド時にそれを静的コンテンツとしてプリレンダリングします。つまり findMany() はリクエスト時だけでなくビルド中にも実行されます。npm run build 中にデータベースに到達できなければ、ビルドはそこで失敗します。したがって、このアプリの CI パイプラインには、実行時だけでなくビルド時にも到達可能なデータベースが必要です。
よくある質問
本番環境でもシャドウデータベースは必要ですか?
いいえ。prisma migrate dev は開発中にスキーマの差分を検出するためにこれを使います。本番環境では prisma migrate deploy を使ってください。これは既存のマイグレーションファイルを、シャドウデータベースにまったく触れずに適用します。
なぜ独立したスクリプトが “Cannot read properties of undefined (reading ‘prepareCacheLength’)” で失敗するのですか?
そのスクリプトの環境ではprocess.env.DATABASE_URL が undefined です。Next.js は next dev と next build のために .env を自動的に読み込みますが、素の node や tsx のスクリプトは読み込みません。スクリプトの先頭に import "dotenv/config" を追加してください。
代わりに @prisma/adapter-pg の MySQL 版を使えますか?
MySQL 固有のアダプター名はありません。@prisma/adapter-mariadb が、Prisma が MariaDB と MySQL の両方 (VillageSQL を含む) のために提供しているものです。
トラブルシューティング
関連項目
- Next.js と Drizzle で MySQL を使う — Prisma の代わりに、より軽量で SQL ファーストの ORM で構築した同じアプリ
- Next.js で MySQL を使う — ORM を一切使わない接続設定、Server Actions、Route Handler のパターン
- ORM で MySQL を使う — Prisma だけでなく、あらゆる ORM で重要な設定
- コネクションプーリング — ドライバーアダプターのプールサイズがプロセス数とどう相互作用するか