跳至主要內容

PlanetScale

Prisma 和 PlanetScale 結合,透過使用 Prisma ORM 和 PlanetScale 高度可擴展的 MySQL 平台,提供了一個能優化快速且型別安全的資料存取應用程式開發環境。

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

什麼是 PlanetScale?

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

  • 企業級可擴展性。 PlanetScale 提供高可用性的正式環境資料庫叢集,支援跨多個資料庫伺服器的擴展。這在 Serverless 環境中特別有用,因為它可以避免必須管理連線限制的問題。
  • 資料庫分支。 PlanetScale 允許您建立資料庫 Schema 分支,讓您可以在將變更套用到正式環境資料庫之前,先在開發分支上測試變更。
  • 支援非阻塞式 Schema 變更 PlanetScale 提供的工作流允許使用者更新資料庫 Schema,而無需鎖定資料庫或導致停機。

與其他資料庫提供者的共通點

在 PlanetScale 上使用 Prisma ORM 的許多方面,就跟在任何其他關聯式資料庫上使用 Prisma ORM 一樣。您仍然可以:

需考慮的差異

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

  • 分支與部署請求。 PlanetScale 提供兩種類型的資料庫分支:開發分支 (development branches) 允許您測試 Schema 變更,而 正式環境分支 (production branches) 則受到保護,防止直接進行 Schema 變更。相反地,變更必須先在開發分支上建立,然後使用部署請求部署到正式環境。正式環境分支具備高可用性,並包含每日自動備份。欲了解更多資訊,請參閱如何使用分支與部署請求

  • 參照動作與完整性。 為了支援跨多個資料庫伺服器的擴展,PlanetScale 預設不使用外鍵約束 (foreign key constraints)(這在關聯式資料庫中通常用於強制執行不同資料表之間的資料關係),並要求使用者在應用程式中手動處理。不過,您可以明確地在 PlanetScale 資料庫設定中啟用它們。如果您沒有明確啟用這些功能,您仍然可以透過使用 Prisma ORM 的 prisma 關聯模式在 Prisma Client 中模擬關聯,從而維持資料中的這些關係並允許使用 參照動作 (referential actions)。欲了解更多資訊,請參閱方法 1:在 Prisma Client 中模擬關聯

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

  • 使用 db push 進行 Schema 變更。 當您將開發分支合併到正式環境分支時,PlanetScale 會自動比較兩個 Schema 並產生自己的 Schema 差異(diff)。這意味著 Prisma ORM 的 prisma migrate 工作流(會產生自己的遷移檔案歷史記錄)在與 PlanetScale 搭配使用時並不完全契合。這些遷移檔案可能無法反映分支合併時 PlanetScale 執行的實際 Schema 變更。

    警告

    我們建議在使用 PlanetScale 進行 Schema 變更時,不要使用 prisma migrate。相反地,我們建議您使用 prisma db push 指令。

    有關其運作方式的範例,請參閱如何使用 db push 進行 Schema 變更

  • 內省 (Introspection)。當您對現有資料庫進行內省且 尚未 啟用 PlanetScale 資料庫中的外鍵約束 時,您將得到一個沒有關聯的 Schema,因為關聯通常是根據連接資料表的外鍵來定義的。在這種情況下,您需要手動添加缺失的關聯。欲了解更多資訊,請參閱如何在內省後添加缺失的關聯

如何使用分支與部署請求

使用 Prisma ORM 連接到 PlanetScale 時,您需要為分支使用正確的連接字串。可以在您的 PlanetScale 帳戶中,進入分支的概覽頁面並選擇「Connect」下拉選單來找到特定資料庫分支的連接 URL。在「Passwords」部分,產生新密碼並從下拉選單中選擇「Prisma」以獲取 Prisma 格式的連接 URL。有關如何連接到 PlanetScale 資料庫的更多詳細資訊,請參閱 Prisma ORM 的入門指南

每個 PlanetScale 資料庫在建立時都有一個名為 main 的分支,最初是一個開發分支,您可以用它來測試 Schema 變更。一旦您對在那裡所做的變更感到滿意,就可以將其提升 (promote) 為正式環境分支。請注意,您只能將新變更推送到開發分支,因此進一步的變更需要在單獨的開發分支上建立,隨後再使用部署請求 (deploy request) 部署到正式環境。

如果您嘗試推送到正式環境分支,您將收到錯誤訊息 Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database. (此資料庫已停用直接執行 DDL (資料定義語言) SQL 語句)。

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

方法 1:在 Prisma Client 中模擬關聯

1. 設定 relationMode = "prisma"

PlanetScale 預設不會在其資料庫 Schema 中使用外鍵約束。然而,Prisma ORM 依賴底層資料庫中的外鍵約束來強制執行 Prisma Schema 中模型之間的參照完整性。

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

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

schema.prisma
datasource db {
provider = "mysql"
relationMode = "prisma"
}
資訊

設定關聯模式的功能是在 Prisma ORM 3.1.1 版本中作為 referentialIntegrity 預覽功能引入的,並在 Prisma ORM 4.8.0 及更高版本中正式發布 (Generally Available)。

relationMode 欄位在 Prisma ORM 4.5.0 版本中進行了重新命名,此前名為 referentialIntegrity

如果您在 Prisma Schema 中對 relationMode 欄位使用預設的 "foreignKeys" 選項來使用關聯,PlanetScale 將會報錯,且 Prisma ORM 在嘗試建立外鍵時會輸出 P3021 錯誤訊息。(在 2.27.0 之前的版本中,它會輸出原始的資料庫錯誤。)

2. 在外鍵上建立索引

您在 Prisma Client 中模擬關聯 時,您需要建立自己的索引。以一個包含文章 (posts) 和留言 (comments) 的部落格 Schema 為例,這是一個您會想要添加索引的情況:

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 將此變更添加到您的 Schema 中。

在 4.7.0 及更高版本中,如果您有關聯但關聯純量欄位 (relation scalar field) 上沒有索引,Prisma ORM 會發出警告。欲了解更多資訊,請參閱索引驗證

警告

需要注意的一個問題是,隱式多對多關聯 不能透過這種方式添加索引。如果查詢速度或成本是個問題,在這種情況下,您可能想改用 顯式多對多關聯

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

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

之後您就可以使用 Prisma ORM 並在 Prisma Schema 中定義關聯,而不需要額外的配置。

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

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 Schema 中設定 relationMode = "prisma"
  • 在外鍵上定義額外的索引

此外,內省 (introspection) 會自動在您的 Prisma Schema 中建立關聯欄位,因為它可以偵測到資料庫中的外鍵約束。

如何使用 db push 進行 Schema 變更

要在 PlanetScale 中使用 db push,您首先需要 啟用 Prisma Client 中的關聯模擬。在未啟用參照模擬的情況下推送到您的分支將會產生 錯誤訊息 Foreign keys cannot be created on this database. (此資料庫無法建立外鍵)。

例如,假設您決定在上述部落格文章 Schema 中添加一個新的 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 push 進行 Prisma ORM 自動遷移 的教學。

如何在內省後添加缺失的關聯

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

在使用 npx prisma db pull 進行內省後,您得到的 Schema 可能會缺失一些關聯。例如,以下 Schema 缺失了 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 入門指南

如何在 Prisma Schema 中定義分片鍵 (Shard keys) (預覽版)

分片 (Sharding) 是當資料庫負載增長時進行擴充的常用技術。

v6.10.0 起,Prisma ORM 透過 Prisma Schema 中的 @shardKey@@shardKey 屬性原生支援 PlanetScale 上的分片(作為預覽版功能),您可以將這些屬性應用於模型中應作為資料庫設置中分片鍵的欄位。

為了使用分片鍵屬性,您需要在 generator 中指定 shardKeys 預覽功能

generator client {
provider = "prisma-client"
output = "./generated/prisma"
previewFeatures = ["shardKeys"]
}

現在您可以使用 @shardKey@@shardKey 屬性了

單一資料行分片鍵

model User {
id String @default(uuid())
region String @shardKey
}

多資料行分片鍵

model User {
id String @default(uuid())
country String
customerId String
@@shardKey([country, customerId])
}

如何將 PlanetScale serverless 驅動程式與 Prisma ORM 搭配使用 (預覽版)

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

您可以使用 @prisma/adapter-planetscale 驅動程式適配器 (driver adapter) 將 Prisma ORM 與 PlanetScale serverless 驅動程式搭配使用。驅動程式適配器允許您透過 HTTP 與資料庫通訊。

資訊

此功能自 Prisma ORM v6.16.0 起正式發布 (Generally Available)。

資訊

請確保將連接字串中的 host 值更新為 aws.connect.psdb.cloud。您可以在 這裡 了解更多。

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

安裝 Prisma ORM 的 PlanetScale 適配器、PlanetScale serverless 驅動程式和 undici 套件

npm install @prisma/adapter-planetscale undici
資訊

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

更新您的 Prisma Client 實例以使用 PlanetScale serverless 驅動程式

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

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

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

接著您就可以像平常一樣使用具備完整型別安全性的 Prisma Client。Prisma Migrate、內省 (introspection) 和 Prisma Studio 將繼續使用 Prisma Schema 中定義的連接字串正常運作。

更多關於將 PlanetScale 與 Prisma ORM 搭配使用的資訊

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

這些教學將引導您完成連接到 PlanetScale、推送 Schema 變更以及使用 Prisma Client 的過程。

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

© . This site is unofficial and not affiliated with Prisma Data, Inc.