PlanetScale
Prisma 和 PlanetScale 共同提供了一個開發環境,使用 Prisma 的 ORM 和 PlanetScale 的高度可擴展的 MySQL 平台,優化了資料存取應用程式的快速、類型安全開發。
本文討論了使用 Prisma ORM 和 PlanetScale 背後的概念,解釋了 PlanetScale 和其他資料庫供應商之間的共同點和差異,並引導您完成配置應用程式以與 PlanetScale 整合的過程。
什麼是 PlanetScale?
PlanetScale 使用 Vitess 資料庫叢集系統,以提供與 MySQL 相容的資料庫平台。功能包括:
- 企業級可擴展性。 PlanetScale 提供高度可用的生產資料庫叢集,支援跨多個資料庫伺服器進行擴展。這在無伺服器環境中特別有用,因為它可以避免必須管理連線限制的問題。
- 資料庫分支。 PlanetScale 允許您建立資料庫結構描述的分支,以便您可以在開發分支上測試變更,然後再將其應用於生產資料庫。
- 支援非阻塞結構描述變更。 PlanetScale 提供一個工作流程,允許使用者更新資料庫結構描述,而無需鎖定資料庫或導致停機。
與其他資料庫供應商的共通點
將 Prisma ORM 與 PlanetScale 一起使用的許多方面,就像將 Prisma ORM 與任何其他關聯式資料庫一起使用一樣。您仍然可以
- 使用 Prisma Schema Language 建模您的資料庫
- 在您的結構描述中使用 Prisma ORM 現有的
mysql
資料庫連接器,以及 PlanetScale 提供給您的連線字串 - 如果您在 PlanetScale 中已經有資料庫結構描述,可以使用 內省 用於現有專案
- 使用
db push
將結構描述中的變更推送到資料庫 - 在您的應用程式中使用 Prisma Client 與 PlanetScale 的資料庫伺服器通訊
需要考量的差異
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"
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 中模擬關係時,您需要建立自己的索引。作為您想要新增索引的情況範例,請參考以下具有文章和評論的部落格結構描述:
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
欄位上定義索引
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 結構描述中定義關係,而無需額外配置。
在這種情況下,您可以像使用其他支援外鍵約束的資料庫一樣定義關係,例如:
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
檔案
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 push
的 Prisma ORM 自動遷移教學課程。
如何在內省後新增遺失的關係
注意:本節僅在您使用
relationMode = "prisma"
以使用 Prisma ORM 模擬外鍵約束時才相關。如果您在 PlanetScale 資料庫中啟用了外鍵約束,您可以忽略本節。
在使用 npx prisma db pull
進行內省後,您取得的結構描述可能會遺失一些關係。例如,以下結構描述遺失了 User
和 Post
模型之間的關係:
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?
}
在這種情況下,您需要手動新增關係:
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 時的最佳實務的更多提示,請觀看我們的影片