Turso
本指南討論了使用 Prisma ORM 和 Turso 的概念,解釋了 Turso 與其他資料庫提供商之間的異同,並引導您完成配置應用程式以整合 Turso 的過程。
Prisma ORM 對 Turso 的支援目前處於搶先體驗階段。我們非常感謝您在此 GitHub 討論中提供反饋。
什麼是 Turso?
Turso是一個基於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 還支援遠端資料庫副本和嵌入式副本。嵌入式副本使您能夠在應用程式內部複製主資料庫。
- 進行模式更改。由於 libSQL 使用 HTTP 連線到遠端資料庫,這使其與 Prisma Migrate 不相容。但是,您可以使用
prisma migrate diff建立模式遷移,然後使用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" // will be ignored
}
生成 Prisma Client
npx prisma generate
安裝 libSQL 的 Prisma ORM 驅動介面卡包
npm install @prisma/adapter-libsql
更新您的 Prisma Client 例項
import { PrismaClient } from '@prisma/client'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
const adapter = new PrismaLibSQL({
url: `${process.env.TURSO_DATABASE_URL}`,
authToken: `${process.env.TURSO_AUTH_TOKEN}`,
})
const prisma = new PrismaClient({ adapter })
您可以像往常一樣在專案中使用 Prisma Client,並享受完整的型別安全。
在 prisma.config.ts 中透過驅動介面卡使用 Prisma Migrate(搶先體驗)
從v6.6.0開始,透過 prisma.config.ts 檔案,您可以使用 prisma db push 對資料庫模式進行更改。
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 配置檔案
確保您的專案有一個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 https://: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
}
}
}
})