跳到主要內容

PlanetScale

Prisma 和 PlanetScale 共同提供了一個開發環境,使用 Prisma 的 ORM 和 PlanetScale 的高度可擴展的 MySQL 平台,優化了資料存取應用程式的快速、類型安全開發。

本文討論了使用 Prisma ORM 和 PlanetScale 背後的概念,解釋了 PlanetScale 和其他資料庫供應商之間的共同點和差異,並引導您完成配置應用程式以與 PlanetScale 整合的過程。

什麼是 PlanetScale?

PlanetScale 使用 Vitess 資料庫叢集系統,以提供與 MySQL 相容的資料庫平台。功能包括:

  • 企業級可擴展性。 PlanetScale 提供高度可用的生產資料庫叢集,支援跨多個資料庫伺服器進行擴展。這在無伺服器環境中特別有用,因為它可以避免必須管理連線限制的問題。
  • 資料庫分支。 PlanetScale 允許您建立資料庫結構描述的分支,以便您可以在開發分支上測試變更,然後再將其應用於生產資料庫。
  • 支援非阻塞結構描述變更 PlanetScale 提供一個工作流程,允許使用者更新資料庫結構描述,而無需鎖定資料庫或導致停機。

與其他資料庫供應商的共通點

將 Prisma ORM 與 PlanetScale 一起使用的許多方面,就像將 Prisma ORM 與任何其他關聯式資料庫一起使用一樣。您仍然可以

需要考量的差異

PlanetScale 的分支模型和可擴展性設計意味著還有許多差異需要考量。當您決定將 PlanetScale 與 Prisma ORM 一起使用時,應該注意以下幾點:

  • 分支和部署請求。 PlanetScale 提供兩種資料庫分支類型:開發分支,允許您測試結構描述變更;以及生產分支,受到保護,免受直接結構描述變更的影響。相反,變更必須首先在開發分支上建立,然後使用部署請求部署到生產環境。生產分支具有高可用性,並包含每日自動備份。若要了解更多資訊,請參閱如何使用分支和部署請求

  • 參考動作和完整性。 為了支援跨多個資料庫伺服器的擴展,PlanetScale 預設不使用外鍵約束,外鍵約束通常用於關聯式資料庫中,以強制執行不同表格中資料之間的關係,並要求使用者在其應用程式中手動處理此問題。但是,您可以明確地在 PlanetScale 資料庫設定中啟用它們。如果您未明確啟用這些約束,您仍然可以在資料中維護這些關係,並透過使用 Prisma ORM 的能力來參考動作,以使用 prisma 關係模式在 Prisma Client 中模擬關係。有關更多資訊,請參閱如何在 Prisma Client 中模擬關係

  • 在外鍵上建立索引。在 Prisma ORM 中模擬關係(即,當在資料庫層級使用外鍵約束時),您將需要在外鍵上建立專用索引。在標準 MySQL 資料庫中,如果表格的欄位具有外鍵約束,則會自動在該欄位上建立索引。當 PlanetScale 配置為不使用外鍵約束時,當 Prisma Client 模擬關係時,目前這些索引不會建立,這可能會導致查詢未良好優化的問題。為了避免這種情況,您可以在 Prisma ORM 中建立索引。有關更多資訊,請參閱如何在外部鍵上建立索引

  • 使用 db push 進行結構描述變更。 當您將開發分支合併到生產分支時,PlanetScale 將自動比較兩個結構描述並產生自己的結構描述差異。這表示 Prisma ORM 的 prisma migrate 工作流程(它會產生自己的遷移檔案歷史記錄)在與 PlanetScale 協作時不太自然。這些遷移檔案可能無法反映 PlanetScale 在合併分支時執行的實際結構描述變更。

    警告

    我們建議在使用 PlanetScale 進行結構描述變更時,不要使用 prisma migrate。相反地,我們建議您使用 prisma db push 命令。

    有關此運作方式的範例,請參閱如何使用 db push 進行結構描述變更

  • 內省。當您在現有資料庫上進行內省,並且您啟用PlanetScale 資料庫中的外鍵約束時,您將獲得一個沒有關係的結構描述,因為它們通常是根據連接表格的外鍵來定義的。在這種情況下,您將需要手動新增遺失的關係。有關更多資訊,請參閱如何在內省後新增遺失的關係

如何使用分支和部署請求

當使用 Prisma ORM 連線到 PlanetScale 時,您將需要使用適用於您分支的正確連線字串。給定資料庫分支的連線網址可以從您的 PlanetScale 帳戶中找到,方法是前往分支的總覽頁面並選取「連線」下拉式選單。在「密碼」區段中,產生新密碼並從下拉式選單中選取「Prisma」,以取得連線網址的 Prisma 格式。請參閱 Prisma ORM 的入門指南,以取得有關如何連線到 PlanetScale 資料庫的更多詳細資訊。

每個 PlanetScale 資料庫都使用名為 main 的分支建立,該分支最初是一個開發分支,您可以使用它來測試結構描述變更。一旦您對在那裡所做的變更感到滿意,您可以將其升級成為生產分支。請注意,您只能將新變更推送到開發分支,因此進一步的變更將需要在單獨的開發分支上建立,然後稍後使用部署請求部署到生產環境。

如果您嘗試推送到生產分支,您將收到錯誤訊息 Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database.

如何在 PlanetScale 中使用關係(並啟用參考完整性)

選項 1:在 Prisma Client 中模擬關係

1. 設定 relationMode = "prisma"

PlanetScale 預設在其資料庫結構描述中不使用外鍵約束。但是,Prisma ORM 依賴底層資料庫中的外鍵約束,以強制執行 Prisma 結構描述中模型之間的參考完整性。

在 Prisma ORM 3.1.1 及更高版本中,您可以使用 prisma 關係模式在 Prisma Client 中模擬關係,這樣可以避免在資料庫中需要外鍵約束。

若要在 Prisma Client 中啟用關係模擬,請在 datasource 區塊中將 relationMode 欄位設定為 "prisma"

schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
資訊

設定關係模式的功能作為 Prisma ORM 3.1.1 版本中 referentialIntegrity 預覽功能的一部分引入,並且在 Prisma ORM 4.8.0 及更高版本中普遍可用。

relationMode 欄位在 Prisma ORM 4.5.0 版本中重新命名,之前名為 referentialIntegrity

如果您在 Prisma 結構描述中使用關係,並為 relationMode 欄位使用預設的 "foreignKeys" 選項,則當 PlanetScale 嘗試建立外鍵時,會發生錯誤,而 Prisma ORM 會輸出 P3021 錯誤訊息。(在 2.27.0 之前的版本中,它會輸出原始資料庫錯誤。)

2. 在外鍵上建立索引

您在 Prisma Client 中模擬關係時,您需要建立自己的索引。作為您想要新增索引的情況範例,請參考以下具有文章和評論的部落格結構描述:

schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
content String
likes Int @default(0)
comments Comment[]
}

model Comment {
id Int @id @default(autoincrement())
comment String
postId Int
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
}

Comment 模型中的 postId 欄位參考 Post 模型中對應的 id 欄位。但是,這並未在 PlanetScale 中作為外鍵實作,因此該欄位沒有自動索引。這表示某些查詢可能未良好優化。例如,如果您查詢具有特定文章 id 的所有評論,PlanetScale 可能必須執行完整表格查找。這可能會很慢,而且由於 PlanetScale 的計費模型按讀取的列數收費,因此也可能很昂貴。

為了避免這種情況,您可以使用 Prisma ORM 的 @@index 引數postId 欄位上定義索引

schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
content String
likes Int @default(0)
comments Comment[]
}

model Comment {
id Int @id @default(autoincrement())
comment String
postId Int
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)

@@index([postId])
}

然後,您可以使用 db push 將此變更新增至您的結構描述。

在 4.7.0 及更高版本中,如果您的關係在關係純量欄位上沒有索引,Prisma ORM 會向您發出警告。有關更多資訊,請參閱索引驗證

警告

需要注意的一個問題是,隱式多對多關係無法以這種方式新增索引。如果查詢速度或成本是問題,您可能反而想要在這種情況下使用顯式多對多關係

選項 2:在 PlanetScale 資料庫設定中啟用外鍵約束

PlanetScale 資料庫中對外鍵約束的支援自 2024 年 2 月起已正式發布。請按照PlanetScale 文件中的指示,在您的資料庫中啟用它們。

然後,您可以使用 Prisma ORM 並在 Prisma 結構描述中定義關係,而無需額外配置。

在這種情況下,您可以像使用其他支援外鍵約束的資料庫一樣定義關係,例如:

schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
content String
likes Int @default(0)
comments Comment[]
}

model Comment {
id Int @id @default(autoincrement())
comment String
postId Int
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
}

使用這種方法,不需要

  • 在您的 Prisma 結構描述中設定 relationMode = "prisma"
  • 在外鍵上定義額外索引

此外,內省將自動在您的 Prisma 結構描述中建立關係欄位,因為它可以偵測資料庫中的外鍵約束。

如何使用 db push 進行結構描述變更

若要將 db push 與 PlanetScale 一起使用,您首先需要啟用 Prisma Client 中的關係模擬。在未啟用參考模擬的情況下推送到您的分支將會產生錯誤訊息 Foreign keys cannot be created on this database.

舉例來說,假設您決定在上面的部落格文章結構描述中新增一個新的 excerpt 欄位。您首先需要建立新的開發分支並連線到它

接下來,將以下內容新增至您的 schema.prisma 檔案

schema.prisma
model Post {
id Int @id @default(autoincrement())
title String
content String
excerpt String?
likes Int @default(0)
comments Comment[]
}

model Comment {
id Int @id @default(autoincrement())
comment String
postId Int
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)

@@index([postId])
}

若要推送這些變更,請在您的終端機中導覽至您的專案目錄並執行:

npx prisma db push

一旦您對開發分支上的變更感到滿意,您可以開啟部署請求以將這些變更部署到您的生產分支。

如需更多範例,請參閱 PlanetScale 上關於使用 db pushPrisma ORM 自動遷移教學課程

如何在內省後新增遺失的關係

注意:本節僅在您使用 relationMode = "prisma" 以使用 Prisma ORM 模擬外鍵約束時才相關。如果您在 PlanetScale 資料庫中啟用了外鍵約束,您可以忽略本節。

在使用 npx prisma db pull 進行內省後,您取得的結構描述可能會遺失一些關係。例如,以下結構描述遺失了 UserPost 模型之間的關係:

schema.prisma
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String @db.VarChar(255)
content String?
authorId Int

@@index([authorId])
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}

在這種情況下,您需要手動新增關係:

schema.prisma
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String @db.VarChar(255)
content String?
author User @relation(fields: [authorId], references: [id])
authorId Int

@@index([authorId])
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}

如需更詳細的範例,請參閱 PlanetScale 入門指南

如何將 PlanetScale 無伺服器驅動程式與 Prisma ORM 一起使用(預覽)

PlanetScale 無伺服器驅動程式 提供了一種透過 HTTP 與您的資料庫通訊並執行查詢的方式。

您可以將 Prisma ORM 與 PlanetScale 無伺服器驅動程式一起使用,方法是使用 @prisma/adapter-planetscale 驅動程式介面卡。驅動程式介面卡允許您透過 HTTP 與您的資料庫通訊。

資訊

此功能在 Prisma ORM 5.4.2 及更高版本中以預覽形式提供。

若要開始使用,請啟用 driverAdapters 預覽功能旗標

generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}

產生 Prisma Client

npx prisma generate
資訊

請確保您在連線字串中將主機值更新為 aws.connect.psdb.cloud。您可以在此處瞭解更多資訊。

DATABASE_URL='mysql://johndoe:strongpassword@aws.connect.psdb.cloud/clear_nightsky?sslaccept=strict'

安裝適用於 PlanetScale 的 Prisma ORM 介面卡、PlanetScale 無伺服器驅動程式和 undici 套件

npm install @prisma/adapter-planetscale @planetscale/database undici
資訊

當使用低於 18 的 Node.js 版本時,您必須提供自訂的 fetch 函數實作。我們建議使用 undici 套件,Node 的內建 fetch 是基於該套件。Node.js 18 及更高版本包含內建的全域 fetch 函數,因此您不必安裝額外的套件。

更新您的 Prisma Client 執行個體以使用 PlanetScale 無伺服器驅動程式

import { Client } from '@planetscale/database'
import { PrismaPlanetScale } from '@prisma/adapter-planetscale'
import { PrismaClient } from '@prisma/client'
import dotenv from 'dotenv'
import { fetch as undiciFetch } from 'undici'

dotenv.config()
const connectionString = `${process.env.DATABASE_URL}`

const client = new Client({ url: connectionString, fetch: undiciFetch })
const adapter = new PrismaPlanetScale(client)
const prisma = new PrismaClient({ adapter })

然後,您可以像平常一樣使用具有完整類型安全性的 Prisma Client。Prisma Migrate、內省和 Prisma Studio 將繼續像以前一樣使用 Prisma 結構描述中定義的連線字串。

有關將 PlanetScale 與 Prisma ORM 一起使用的更多資訊

開始將 PlanetScale 與 Prisma ORM 一起使用的最快方法是參考我們的入門文件

這些教學課程將引導您完成連線到 PlanetScale、推送結構描述變更和使用 Prisma Client 的過程。

有關一起使用 Prisma ORM 和 PlanetScale 時的最佳實務的更多提示,請觀看我們的影片