Turso
本指南讨论了使用 Prisma ORM 和 Turso 背后的概念,解释了 Turso 和其他数据库提供商之间的共性和差异,并引导您完成配置应用程序以与 Turso 集成的过程。
Prisma ORM 对 Turso 的支持目前处于抢先体验阶段。我们欢迎您在此GitHub 讨论中提供您的反馈。
什么是 Turso?
Turso是一个边缘托管的分布式数据库,它基于 libSQL,libSQL 是 SQLite 的开源和开放贡献分支,使您能够将数据更靠近您的应用程序,并最大限度地减少查询延迟。 Turso 也可以托管在远程服务器上。
Prisma ORM 5.4.2 及更高版本在抢先体验中提供对 Turso 的支持。
与其他数据库提供商的共性
libSQL 与 SQLite 100% 兼容。 libSQL 扩展了 SQLite 并添加了以下特性和功能
- 支持复制
- 支持自动备份
- 能够将 Turso 嵌入为其他程序(如 Linux 内核)的一部分
- 支持用户自定义函数
- 支持异步 I/O
要了解有关 libSQL 与 SQLite 之间差异的更多信息,请参阅 libSQL 宣言。
将 Prisma ORM 与 Turso 结合使用的许多方面与将 Prisma ORM 与任何其他关系数据库结合使用非常相似。您仍然可以
- 使用 Prisma Schema Language 对数据库进行建模
- 在您的 schema 中使用 Prisma ORM 现有的
sqlite
数据库连接器 - 在您的应用程序中使用 Prisma Client 与 Turso 的数据库服务器通信
需要考虑的差异
Turso 和 SQLite 之间存在许多需要考虑的差异。当您决定使用 Turso 和 Prisma ORM 时,您应该注意以下几点
- 远程和嵌入式 SQLite 数据库。 libSQL 使用 HTTP 连接到远程 SQLite 数据库。 libSQL 还支持远程数据库副本和嵌入式副本。 嵌入式副本使您能够在应用程序内部复制主数据库。
- 进行 schema 更改。由于 libSQL 使用 HTTP 连接到远程数据库,因此它与 Prisma Migrate 不兼容。但是,您可以使用
prisma migrate diff
创建 schema 迁移,然后使用 Turso 的 CLI 将更改应用到您的数据库。
如何连接和查询 Turso 数据库
后续部分介绍了如何创建 Turso 数据库、检索数据库凭据以及连接到数据库。
如何配置数据库并检索数据库凭据
确保您已安装 Turso CLI 以管理您的数据库。
如果您没有现有的数据库,您可以运行以下命令来配置数据库
turso db create turso-prisma-db
上面的命令将在离您位置最近的区域创建一个数据库。
运行以下命令来检索数据库的连接字符串
turso db show turso-prisma-db
接下来,创建一个身份验证令牌,该令牌将允许您连接到数据库
turso db tokens create turso-prisma-db
使用身份验证令牌和连接字符串更新您的 .env
文件
TURSO_AUTH_TOKEN="eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."
TURSO_DATABASE_URL="libsql://turso-prisma-db-user.turso.io"
如何连接到 Turso 数据库
要开始使用,请启用 driverAdapters
预览功能标志
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
生成 Prisma Client
npx prisma generate
安装 libSQL 数据库客户端和用于 libSQL 包的 Prisma ORM 驱动程序适配器
npm install @libsql/client @prisma/adapter-libsql
更新您的 Prisma Client 实例
import { PrismaClient } from '@prisma/client'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
import { createClient } from '@libsql/client'
const libsql = createClient({
url: `${process.env.TURSO_DATABASE_URL}`,
authToken: `${process.env.TURSO_AUTH_TOKEN}`,
})
const adapter = new PrismaLibSQL(libsql)
const prisma = new PrismaClient({ adapter })
您可以像往常一样在您的项目中使用 Prisma Client,并具有完整的类型安全。
在 prisma.config.ts
中通过驱动程序适配器使用 Prisma Migrate(抢先体验)
从 v6.6.0 开始,使用 prisma.config.ts
文件,您可以使用 prisma db push
对数据库 schema 进行更改。
1. 安装 LibSQL 驱动程序适配器
在您的终端中运行此命令
npm install @prisma/adapter-libsql
2. 设置环境变量
为了设置 LibSQL 适配器,您需要将一些密钥添加到 .env
文件中
LIBSQL_DATABASE_URL
:您的 Turso 数据库实例的连接 URL。LIBSQL_DATABASE_TOKEN
:您的 Turso 数据库实例的令牌。
然后,您可以将这些添加到您的 .env
文件,或者如果它们存储在不同的密钥存储中,则直接使用它们
LIBSQL_DATABASE_URL="..."
LIBSQL_DATABASE_TOKEN="..."
3. 设置 Prisma Config 文件
确保您的项目有一个 prisma.config.ts
文件。然后,设置 迁移驱动程序适配器 以使用 PrismaLibSQL
import path from 'node:path'
import { defineConfig } from 'prisma/config'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
// import your .env file
import 'dotenv/config'
type Env = {
LIBSQL_DATABASE_URL: string
LIBSQL_DATABASE_TOKEN: string
}
export default defineConfig<Env>({
earlyAccess: true,
schema: path.join('prisma', 'schema.prisma'),
migrate: {
async adapter(env) {
return new PrismaLibSQL({
url: env.LIBSQL_DATABASE_URL,
authToken: env.LIBSQL_DATABASE_TOKEN,
})
}
}
})
4. 迁移您的数据库
Prisma Migrate 现在将根据 prisma.config.ts
中提供的配置,针对您的远程 Turso 数据库运行迁移。
要使用此工作流程创建您的第一个迁移,请运行以下命令
npx prisma db push
嵌入式 Turso 数据库副本
Turso 支持 嵌入式副本。 Turso 的嵌入式副本使您能够在应用程序内部拥有主远程数据库的副本。 嵌入式副本的行为类似于本地 SQLite 数据库。 数据库查询速度更快,因为您的数据库位于您的应用程序内部。
嵌入式数据库副本的工作原理
当您的应用程序最初建立与数据库的连接时,主数据库将满足查询
Turso 将 (1) 在您的应用程序内部创建一个嵌入式副本,并 (2) 将数据从您的主数据库复制到该副本,使其在本地可用
嵌入式副本将满足后续的读取查询。 libSQL 客户端提供了一个 sync()
方法,您可以调用该方法以确保嵌入式副本的数据保持最新。
借助嵌入式副本,此设置保证了应用程序的响应性,因为数据将在本地轻松可用且访问速度更快。
与您可能熟悉的读取副本设置类似,写入操作将转发到主远程数据库并在传播到所有嵌入式副本之前执行。
- 写入操作传播已转发到数据库。
- 数据库使用来自 1 的更新响应服务器。
- 写入操作已传播到数据库副本。
您的应用程序的数据需求将决定您应该多久在远程数据库和嵌入式数据库副本之间同步数据。 例如,您可以使用中间件函数(例如 Express 和 Fastify)或 cron 作业来同步数据。
如何在远程数据库和嵌入式副本之间同步数据
要开始将嵌入式副本与 Prisma ORM 结合使用,请在您的应用程序中添加 libSQL 中的 sync()
方法。 下面的示例展示了如何使用 Express 中间件同步数据。
import express from 'express'
const app = express()
// ... the rest of your application code
app.use(async (req, res, next) => {
await libsql.sync()
next()
})
app.listen(3000, () => console.log(`Server ready at http://localhost:3000`))
它也可以作为 Prisma Client 扩展来实现。 下面的示例显示了在执行创建、更新或删除操作后自动同步。
const prisma = new PrismaClient().$extends({
query: {
$allModels: {
async $allOperations({ operation, model, args, query }) {
const result = await query(args)
// Synchronize the embedded replica after any write operation
if (['create', 'update', 'delete'].includes(operation)) {
await libsql.sync()
}
return result
}
}
}
})