PlanetScale
Prisma 和 PlanetScale 共同提供了一个开发平台,使用 Prisma 的 ORM 和 PlanetScale 的高度可扩展的基于 MySQL 的平台,优化数据访问应用的快速、类型安全的开发。
¥Prisma and PlanetScale together provide a development arena that optimizes rapid, type-safe development of data access applications, using Prisma's ORM and PlanetScale's highly scalable MySQL-based platform.
本文档讨论使用 Prisma ORM 和 PlanetScale 背后的概念,解释 PlanetScale 与其他数据库提供商之间的共性和差异,并引导你完成配置应用以与 PlanetScale 集成的过程。
¥This document discusses the concepts behind using Prisma ORM and PlanetScale, explains the commonalities and differences between PlanetScale and other database providers, and leads you through the process for configuring your application to integrate with PlanetScale.
什么是 PlanetScale?
¥What is PlanetScale?
PlanetScale 采用 Vitess 数据库集群系统,提供兼容 MySQL 的数据库平台。特点包括:
¥PlanetScale uses the Vitess database clustering system to provide a MySQL-compatible database platform. Features include:
-
企业可扩展性。PlanetScale 提供高度可用的生产数据库集群,支持跨多个数据库服务器进行扩展。这在无服务器环境中特别有用,因为它避免了必须 管理连接限制。
¥Enterprise scalability. PlanetScale provides a highly available production database cluster that supports scaling across multiple database servers. This is particularly useful in a serverless context, as it avoids the problem of having to manage connection limits.
-
数据库分支。PlanetScale 允许你创建 数据库模式的分支,以便你可以在将更改应用到生产数据库之前在开发分支上测试更改。
¥Database branches. PlanetScale allows you to create branches of your database schema, so that you can test changes on a development branch before applying them to your production database.
-
支持 非阻塞架构更改。PlanetScale 提供了一个工作流程,允许用户更新数据库架构,而无需锁定数据库或导致停机。
¥Support for non-blocking schema changes. PlanetScale provides a workflow that allows users to update database schemas without locking the database or causing downtime.
与其他数据库提供商的共同点
¥Commonalities with other database providers
将 Prisma ORM 与 PlanetScale 结合使用的许多方面就像将 Prisma ORM 与任何其他关系数据库结合使用一样。你仍然可以:
¥Many aspects of using Prisma ORM with PlanetScale are just like using Prisma ORM with any other relational database. You can still:
-
使用 Prisma 模式语言 为你的数据库建模
¥model your database with the Prisma Schema Language
-
在你的架构中使用 Prisma ORM 的现有
mysql
数据库连接器 以及 PlanetScale 为你提供的连接字符串¥use Prisma ORM's existing
mysql
database connector in your schema, along with the connection string PlanetScale provides you -
如果你在 PlanetScale 中已有数据库架构,请对现有项目使用 内省
¥use Introspection for existing projects if you already have a database schema in PlanetScale
-
使用
db push
将架构中的更改推送到数据库¥use
db push
to push changes in your schema to the database -
在应用中使用 Prisma 客户端 与 PlanetScale 的数据库服务器通信
¥use Prisma Client in your application to talk to the database server at PlanetScale
需要考虑的差异
¥Differences to consider
PlanetScale 的分支模型和可扩展性设计意味着还需要考虑许多差异。在决定将 PlanetScale 与 Prisma ORM 结合使用时,你应该注意以下几点:
¥PlanetScale's branching model and design for scalability means that there are also a number of differences to consider. You should be aware of the following points when deciding to use PlanetScale with Prisma ORM:
-
分支和部署请求。PlanetScale 提供两种类型的数据库分支:开发分支(允许你测试架构更改)和生产分支(不受直接架构更改的影响)。相反,必须首先在开发分支上创建更改,然后使用部署请求将其部署到生产中。生产分支具有高可用性,并且包括自动每日备份。要了解更多信息,请参阅 如何使用分支和部署请求。
¥Branching and deploy requests. PlanetScale provides two types of database branches: development branches, which allow you to test out schema changes, and production branches, which are protected from direct schema changes. Instead, changes must be first created on a development branch and then deployed to production using a deploy request. Production branches are highly available and include automated daily backups. To learn more, see How to use branches and deploy requests.
-
参考行动和诚信。为了支持跨多个数据库服务器的扩展,PlanetScale 默认情况下不使用外键约束(通常在关系数据库中使用,以强制不同表中的数据之间的关系)并要求用户在其应用中手动处理此问题。但是,你可以明确 在 PlanetScale 数据库设置中启用它们。如果你没有明确启用这些关系,你仍然可以在数据中维护这些关系,并通过使用 Prisma ORM 的 在 Prisma 客户端中模拟关系 和
prisma
关系模式的功能来允许使用 参考行动。欲了解更多信息,请参阅 如何在 Prisma 客户端中模拟关系。¥Referential actions and integrity. To support scaling across multiple database servers, PlanetScale by default does not use foreign key constraints, which are normally used in relational databases to enforce relationships between data in different tables, and asks users to handle this manually in their applications. However, you can explicitly enable them in the PlanetScale database settings. If you don't enable these explicitly, you can still maintain these relationships in your data and allow the use of referential actions by using Prisma ORM's ability to emulate relations in Prisma Client with the
prisma
relation mode. For more information, see How to emulate relations in Prisma Client. -
在外键上创建索引。当 在 Prisma ORM 中模拟关系 时(即在数据库级别不使用外键约束时),你将需要在外键上创建专用索引。在标准 MySQL 数据库中,如果表有一列带有外键约束,则会自动在该列上创建索引。当 PlanetScale 配置为不使用外键约束时,Prisma 客户端模拟关系时不会创建这些索引 currently,这可能会导致查询未得到很好优化的问题。为了避免这种情况,你可以在 Prisma ORM 中创建索引。欲了解更多信息,请参阅 如何在外键上创建索引。
¥Creating indexes on foreign keys. When emulating relations in Prisma ORM (i.e. when not using foreign key constraints on the database-level), you will need to create dedicated indexes on foreign keys. In a standard MySQL database, if a table has a column with a foreign key constraint, an index is automatically created on that column. When PlanetScale is configured to not use foreign key constraints, these indexes are currently not created when Prisma Client emulates relations, which can lead to issues with queries not being well optimized. To avoid this, you can create indexes in Prisma ORM. For more information, see How to create indexes on foreign keys.
-
使用
db push
进行架构更改。当你将开发分支合并到生产分支时,PlanetScale 将自动比较两个架构并生成自己的架构差异。这意味着 Prisma ORM 的prisma migrate
工作流程(生成自己的迁移文件历史记录)在与 PlanetScale 一起使用时并不自然。这些迁移文件可能无法反映合并分支时 PlanetScale 运行的实际架构更改。¥Making schema changes with
db push
. When you merge a development branch into your production branch, PlanetScale will automatically compare the two schemas and generate its own schema diff. This means that Prisma ORM'sprisma migrate
workflow, which generates its own history of migration files, is not a natural fit when working with PlanetScale. These migration files may not reflect the actual schema changes run by PlanetScale when the branch is merged.warning我们建议在使用 PlanetScale 进行架构更改时不要使用
prisma migrate
。相反,我们建议你使用prisma db push
命令。¥We recommend not using
prisma migrate
when making schema changes with PlanetScale. Instead, we recommend that you use theprisma db push
command.有关其工作原理的示例,请参阅 如何使用
db push
进行架构更改¥For an example of how this works, see How to make schema changes with
db push
-
内省。当你对现有数据库进行内省并且未启用 PlanetScale 数据库中的外键约束 时,你将得到一个没有关系的模式,因为它们通常是基于连接表的外键定义的。在这种情况下,你将需要手动添加缺少的关系。欲了解更多信息,请参阅 内省后如何添加缺失的关系。
¥Introspection. When you introspect on an existing database and you have not enabled foreign key constraints in your PlanetScale database, you will get a schema with no relations, as they are usually defined based on foreign keys that connect tables. In that case, you will need to add the missing relations in manually. For more information, see How to add in missing relations after Introspection.
如何使用分支和部署请求
¥How to use branches and deploy requests
使用 Prisma ORM 连接到 PlanetScale 时,你需要为你的分支使用正确的连接字符串。通过转到分支的概述页面并选择 'Connect' 下拉列表,可以从你的 PlanetScale 账户找到给定数据库分支的连接 URL。在 '密码' 部分中,生成新密码并从下拉列表中选择 'Prisma' 以获取连接 URL 的 Prisma 格式。有关如何连接到 PlanetScale 数据库的更多详细信息,请参阅 Prisma ORM 的 入门指南。
¥When connecting to PlanetScale with Prisma ORM, you will need to use the correct connection string for your branch. The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' from the dropdown to get the Prisma format for the connection URL. See Prisma ORM's Getting Started guide for more details of how to connect to a PlanetScale database.
每个 PlanetScale 数据库都是使用名为 main
的分支创建的,该分支最初是一个开发分支,可用于测试架构更改。一旦你对在那里所做的更改感到满意,你就可以 推广它 成为生产分支。请注意,你只能将新更改推送到开发分支,因此需要在单独的开发分支上创建进一步的更改,然后使用 部署请求 部署到生产环境。
¥Every PlanetScale database is created with a branch called main
, which is initially a development branch that you can use to test schema changes on. Once you are happy with the changes you make there, you can promote it to become a production branch. Note that you can only push new changes to a development branch, so further changes will need to be created on a separate development branch and then later deployed to production using a deploy request.
如果你尝试推送到生产分支,你将得到 错误信息 Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database.
¥If you try to push to a production branch, you will get the error message Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database.
如何通过 PlanetScale 使用关系(并启用引用完整性)
¥How to use relations (and enable referential integrity) with PlanetScale
选项 1:在 Prisma 客户端中模拟关系
¥Option 1: Emulate relations in Prisma Client
1. 设置 relationMode = "prisma"
¥ Set relationMode = "prisma"
默认情况下,PlanetScale 不在其数据库架构中使用外键约束。但是,Prisma ORM 依赖底层数据库中的外键约束来强制 Prisma 架构中的模型之间的引用完整性。
¥PlanetScale does not use foreign key constraints in its database schema by default. However, Prisma ORM relies on foreign key constraints in the underlying database to enforce referential integrity between models in your Prisma schema.
在 Prisma ORM 版本 3.1.1 及更高版本中,你可以 使用 prisma
关系模式在 Prisma Client 中模拟关系,这避免了数据库中需要外键约束。
¥In Prisma ORM versions 3.1.1 and later, you can emulate relations in Prisma Client with the prisma
relation mode, which avoids the need for foreign key constraints in the database.
要在 Prisma Client 中启用关系模拟,请将 datasource
块中的 relationMode
字段设置为 "prisma"
:
¥To enable emulation of relations in Prisma Client, set the relationMode
field to "prisma"
in the datasource
block:
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
。
¥The ability to set the relation mode was introduced as part of the referentialIntegrity
preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.
The relationMode
field was renamed in Prisma ORM version 4.5.0, and was previously named referentialIntegrity
.
如果你在 Prisma 架构中使用关系,并且 relationMode
字段使用默认的 "foreignKeys"
选项,PlanetScale 将出错,并且 Prisma ORM 在尝试创建外键时会输出 P3021 错误信息。(在 2.27.0 之前的版本中,它将输出原始数据库错误。)
¥If you use relations in your Prisma schema with the default "foreignKeys"
option for the relationMode
field, PlanetScale will error and Prisma ORM output the P3021 error message when it tries to create foreign keys. (In versions before 2.27.0 it will output a raw database error.)
2. 在外键上创建索引
¥ Create indexes on foreign keys
当 你在 Prisma 客户端中模拟关系 时,你需要创建自己的索引。作为你想要添加索引的情况的示例,请采用包含帖子和评论的博客的此架构:
¥When you emulate relations in Prisma Client, you need to create your own indexes. As an example of a situation where you would want to add an index, take this schema for a blog with posts and comments:
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 的计费模型按读取的行数收费。
¥The postId
field in the Comment
model refers to the corresponding id
field in the Post
model. However this is not implemented as a foreign key in PlanetScale, so the column doesn't have an automatic index. This means that some queries may not be well optimized. For example, if you query for all comments with a certain post id
, PlanetScale may have to do a full table lookup. This could be slow, and also expensive because PlanetScale's billing model charges for the number of rows read.
为了避免这种情况,你可以使用 Prisma ORM 的 @@index
参数 在 postId
字段上定义索引:
¥To avoid this, you can define an index on the postId
field using Prisma ORM's @@index
argument:
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
中。
¥You can then add this change to your schema using db push
.
在版本 4.7.0 及更高版本中,如果你的关系标量字段上没有索引,Prisma ORM 会向你触发警告。欲了解更多信息,请参阅 索引验证。
¥In versions 4.7.0 and later, Prisma ORM warns you if you have a relation with no index on the relation scalar field. For more information, see Index validation.
需要注意的一个问题是 隐式多对多关系 不能以这种方式添加索引。如果查询速度或成本是一个问题,在这种情况下你可能想使用 显式多对多关系。
¥One issue to be aware of is that implicit many-to-many relations cannot have an index added in this way. If query speed or cost is an issue, you may instead want to use an explicit many-to-many relation in this case.
选项 2:在 PlanetScale 数据库设置中启用外键约束
¥Option 2: Enable foreign key constraints in the PlanetScale database settings
自 2024 年 2 月起,PlanetScale 数据库中已普遍提供对外键约束的支持。按照 PlanetScale 文档 中的说明在你的数据库中启用它们。
¥Support for foreign key constraints in PlanetScale databases has been Generally Available since February 2024. Follow the instructions in the PlanetScale documentation to enable them in your database.
然后,你可以使用 Prisma ORM 并在 Prisma 架构中定义关系,而无需额外配置。
¥You can then use Prisma ORM and define relations in your Prisma schema without the need for extra configuration.
在这种情况下,你可以像其他支持外键约束的数据库一样定义关系,例如:
¥In that case, you can define a relation as with other database that supports foreign key constraints, for example:
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)
}
通过这种方法,没有必要:
¥With this approach, it is not necessary to:
-
在 Prisma 架构中设置
relationMode = "prisma"
¥set
relationMode = "prisma"
in your Prisma schema -
在外键上定义附加索引
¥define additional indexes on foreign keys
此外,内省将自动在 Prisma 模式中创建关系字段,因为它可以检测数据库中的外键约束。
¥Also, introspection will automatically create relation fields in your Prisma schema because it can detect the foreign key constraints in the database.
如何使用 db push
进行架构更改
¥How to make schema changes with db push
要将 db push
与 PlanetScale 结合使用,你首先需要 在 Prisma 客户端中启用关系模拟。在未启用参考模拟的情况下推送到你的分支将给出 错误信息 Foreign keys cannot be created on this database.
¥To use db push
with PlanetScale, you will first need to enable emulation of relations in Prisma Client. Pushing to your branch without referential emulation enabled will give the error message Foreign keys cannot be created on this database.
举个例子,假设你决定向上面的博客文章架构添加一个新的 excerpt
字段。你首先需要 创建一个新的开发分支并连接到它。
¥As an example, let's say you decide to decide to add a new excerpt
field to the blog post schema above. You will first need to create a new development branch and connect to it.
接下来,将以下内容添加到 schema.prisma
文件中:
¥Next, add the following to your schema.prisma
file:
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])
}
要推送这些更改,请导航到终端中的项目目录并运行
¥To push these changes, navigate to your project directory in your terminal and run
npx prisma db push
一旦你对开发分支上的更改感到满意,你就可以打开部署请求以将这些更改部署到生产分支。
¥Once you are happy with your changes on your development branch, you can open a deploy request to deploy these to your production branch.
有关更多示例,请参阅 PlanetScale 关于使用 db push
的 使用 Prisma ORM 自动迁移 的教程。
¥For more examples, see PlanetScale's tutorial on automatic migrations with Prisma ORM using db push
.
如何在自省后添加缺失的关系
¥How to add in missing relations after introspection
注意:仅当你使用
relationMode = "prisma"
通过 Prisma ORM 模拟外键约束时,本节才相关。如果你在 PlanetScale 数据库中启用了外键约束,则可以忽略此部分。¥Note: This section is only relevant if you use
relationMode = "prisma"
to emulate foreign key constraints with Prisma ORM. If you enabled foreign key constraints in your PlanetScale database, you can ignore this section.
使用 npx prisma db pull
进行内省后,你得到的模式可能缺少一些关系。例如,以下架构缺少 User
和 Post
模型之间的关系:
¥After introspecting with npx prisma db pull
, the schema you get may be missing some relations. For example, the following schema is missing a relation between the User
and Post
models:
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?
}
在这种情况下,你需要手动添加关系:
¥In this case you need to add the relation in manually:
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 入门指南。
¥For a more detailed example, see the Getting Started guide for PlanetScale.
如何在 Prisma 模式中定义分片键(预览版)
¥How to define shard keys in your Prisma schema (Preview)
分片 是一种在数据库负载增加时进行扩展的常用技术。
¥Sharding is a popular technique to scale up when database load grows.
从 v6.10.0 开始,Prisma ORM 通过 Prisma 模式中的 @shardKey
和 @@shardKey
属性原生支持 PlanetScale 上的分片(作为 预览 的功能),你可以将这些属性应用于模型中应在数据库设置中用作分片键的字段。
¥As of v6.10.0, Prisma ORM supports sharding on PlanetScale natively (as a Preview feature) via the @shardKey
and @@shardKey
attributes in the Prisma schema which you can apply to the fields in your models that should serve as shard keys in your database setup.
要使用分片键属性,你需要在 generator
上指定 shardKeys
预览功能:
¥In order to use the shard key attributes, you need to specify the shardKeys
Preview feature on your generator
:
generator client {
provider = "prisma-client-js"
output = "../generated/prisma"
previewFeatures = ["shardKeys"]
}
现在你可以使用 @shardKey
和 @@shardKey
属性:
¥Now you can use the @shardKey
and @@shardKey
attributes:
单列分片键
¥Single-column shard key
model User {
id String @default(uuid())
region String @shardKey
}
多列分片键
¥Multi-column shard key
model User {
id String @default(uuid())
country String
customerId String
@@shardKey([country, customerId])
}
如何将 PlanetScale 无服务器驱动程序与 Prisma ORM 结合使用(预览版)
¥How to use the PlanetScale serverless driver with Prisma ORM (Preview)
PlanetScale 无服务器驱动程序 提供了一种通过 HTTP 与数据库通信并执行查询的方法。
¥The PlanetScale serverless driver provides a way of communicating with your database and executing queries over HTTP.
你可以使用 Prisma ORM 以及使用 @prisma/adapter-planetscale
驱动程序适配器的 PlanetScale 无服务器驱动程序。驱动程序适配器允许你通过 HTTP 与数据库进行通信。
¥You can use Prisma ORM along with the PlanetScale serverless driver using the @prisma/adapter-planetscale
driver adapter. The driver adapter allows you to communicate with your database over HTTP.
此功能在 Prisma ORM 版本 5.4.2 及更高版本的预览版中可用。
¥This feature is available in Preview from Prisma ORM versions 5.4.2 and later.
首先,启用 driverAdapters
预览功能标志:
¥To get started, enable the driverAdapters
Preview feature flag:
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}
生成 Prisma 客户端:
¥Generate Prisma Client:
npx prisma generate
安装适用于 PlanetScale、PlanetScale 无服务器驱动程序和 undici
软件包的 Prisma ORM 适配器:
¥Install the Prisma ORM adapter for PlanetScale, PlanetScale serverless driver and undici
packages:
npm install @prisma/adapter-planetscale undici
当使用低于 18 的 Node.js 版本时,你必须提供自定义 fetch 函数实现。我们推荐 Node 内置 fetch 所基于的 undici
包。Node.js 版本 18 及更高版本包含内置的全局 fetch
函数,因此你无需安装额外的包。
¥When using a Node.js version below 18, you must provide a custom fetch function implementation. We recommend the undici
package on which Node's built-in fetch is based. Node.js versions 18 and later include a built-in global fetch
function, so you don't have to install an extra package.
更新你的 Prisma 客户端实例以使用 PlanetScale 无服务器驱动程序:
¥Update your Prisma Client instance to use the PlanetScale serverless driver:
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 adapter = new PrismaPlanetScale({ url: connectionString, fetch: undiciFetch })
const prisma = new PrismaClient({ adapter })
然后,你可以像平常一样使用 Prisma 客户端,并具有完全的类型安全性。Prisma Migrate、内省和 Prisma Studio 将继续像以前一样使用 Prisma 架构中定义的连接字符串工作。
¥You can then use Prisma Client as you normally would with full type-safety. Prisma Migrate, introspection, and Prisma Studio will continue working as before using the connection string defined in the Prisma schema.
有关将 PlanetScale 与 Prisma ORM 结合使用的更多信息
¥More on using PlanetScale with Prisma ORM
开始将 PlanetScale 与 Prisma ORM 结合使用的最快方法是参考我们的入门文档:
¥The fastest way to start using PlanetScale with Prisma ORM is to refer to our Getting Started documentation:
这些教程将引导你完成连接到 PlanetScale、推送架构更改以及使用 Prisma Client 的过程。
¥These tutorials will take you through the process of connecting to PlanetScale, pushing schema changes, and using Prisma Client.
有关同时使用 Prisma ORM 和 PlanetScale 时最佳实践的更多提示,请观看我们的视频:
¥For further tips on best practices when using Prisma ORM and PlanetScale together, watch our video: