Appearance
Prisma 数据库连接
Prisma 提供了灵活的数据库连接配置选项,支持多种数据库类型和连接方式。本指南将详细介绍如何配置和管理 Prisma 的数据库连接。
数据源配置
基本数据源配置
在 Prisma Schema 中配置数据源:
prisma
// schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
支持的数据库类型
prisma
// PostgreSQL
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// MySQL
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
// SQLite
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
// SQL Server
datasource db {
provider = "sqlserver"
url = env("DATABASE_URL")
}
// MongoDB (预览功能)
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
连接字符串格式
PostgreSQL 连接字符串
text
# 基本连接
DATABASE_URL="postgresql://username:password@localhost:5432/mydb"
# 带 SSL 选项的连接
DATABASE_URL="postgresql://username:password@localhost:5432/mydb?sslmode=prefer"
# 带 schema 参数的连接
DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public&connection_limit=20"
# 生产环境连接示例
DATABASE_URL="postgresql://user:pass@aws-us-east-1.c1234567890.us-east-1.rds.amazonaws.com:5432/proddb?sslmode=require"
MySQL 连接字符串
text
# 基本连接
DATABASE_URL="mysql://username:password@localhost:3306/mydb"
# 带额外参数的连接
DATABASE_URL="mysql://username:password@localhost:3306/mydb?connection_limit=20&socket_timeout=60"
# 生产环境连接示例
DATABASE_URL="mysql://user:pass@aws-us-east-1.cluster-1234567890.us-east-1.rds.amazonaws.com:3306/proddb"
SQL Server 连接字符串
text
# 基本连接
DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=username;password=password;encrypt=true"
# 详细配置
DATABASE_URL="sqlserver://server.database.windows.net:1433;database=mydb;user=username@server;password=password;encrypt=true;trustServerCertificate=false;loginTimeout=30;isolationLevel=READ_COMMITTED"
SQLite 连接字符串
prisma
// schema.prisma
datasource db {
provider = "sqlite"
url = "file:./dev.db" // 相对路径
// 或
url = "file:/home/user/app.db" // 绝对路径
// 或
url = "file:../shared/db.sql?journal_mode=WAL" // 带参数
}
环境配置
.env 文件配置
text
# 开发环境
DATABASE_URL="postgresql://localhost:5432/myapp_dev"
# 测试环境
TEST_DATABASE_URL="postgresql://localhost:5432/myapp_test"
# 生产环境
DATABASE_URL="postgresql://prod-server:5432/myapp_prod"
不同环境的连接配置
typescript
// utils/prisma.ts
import { PrismaClient } from '@prisma/client'
let prisma: PrismaClient
declare global {
var prisma: PrismaClient | undefined
}
if (process.env.NODE_ENV === 'production') {
prisma = new PrismaClient()
} else {
if (!global.prisma) {
global.prisma = new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
})
}
prisma = global.prisma
}
export default prisma
连接池配置
Prisma Client 连接池
typescript
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL,
},
},
// 连接池选项
__internal: {
// 这些是内部选项,可能会变化
},
})
数据库 URL 中的连接池参数
text
# PostgreSQL 连接池参数
DATABASE_URL="postgresql://user:pass@localhost:5432/mydb?connection_limit=20&pool_timeout=60"
# MySQL 连接池参数
DATABASE_URL="mysql://user:pass@localhost:3306/mydb?connection_limit=20&socket_timeout=60"
安全连接配置
SSL/TLS 配置
text
# PostgreSQL SSL 连接
DATABASE_URL="postgresql://user:pass@host:5432/db?sslmode=require"
# MySQL SSL 连接
DATABASE_URL="mysql://user:pass@host:3306/db?sslaccept=strict"
使用 SSL 证书
typescript
// 使用自定义 SSL 证书
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL,
// 某些部署环境可能需要额外的 SSL 配置
},
},
})
连接测试
测试数据库连接
typescript
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function testConnection() {
try {
// 尝试连接数据库
await prisma.$connect()
console.log('数据库连接成功')
// 执行简单查询测试
await prisma.$queryRaw`SELECT 1`
console.log('数据库查询测试成功')
} catch (error) {
console.error('数据库连接失败:', error)
process.exit(1)
} finally {
await prisma.$disconnect()
}
}
testConnection()
连接健康检查中间件
typescript
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
// 创建健康检查函数
async function healthCheck() {
try {
await prisma.$queryRaw`SELECT 1`
return { status: 'healthy', timestamp: new Date().toISOString() }
} catch (error) {
return {
status: 'unhealthy',
error: error instanceof Error ? error.message : 'Unknown error',
timestamp: new Date().toISOString()
}
}
}
// 在应用中使用
app.get('/health', async (req, res) => {
const status = await healthCheck()
res.status(status.status === 'healthy' ? 200 : 503).json(status)
})
高可用性配置
读写分离(使用多个数据源)
虽然 Prisma 本身不直接支持读写分离,但可以通过以下方式实现:
typescript
// 创建多个 Prisma 客户端实例
const primaryDb = new PrismaClient({
datasources: {
db: { url: process.env.PRIMARY_DATABASE_URL },
},
})
const replicaDb = new PrismaClient({
datasources: {
db: { url: process.env.REPLICA_DATABASE_URL },
},
})
// 根据查询类型选择数据库
class DatabaseService {
static async read(query: any) {
return replicaDb.$queryRaw(query) // 从副本读取
}
static async write(query: any) {
return primaryDb.$executeRaw(query) // 写入主数据库
}
}
连接故障转移
typescript
import { PrismaClient } from '@prisma/client'
class ResilientDatabase {
private primary: PrismaClient
private secondary?: PrismaClient
private isPrimaryHealthy = true
constructor() {
this.primary = new PrismaClient({
datasources: { db: { url: process.env.PRIMARY_DB_URL } },
})
if (process.env.SECONDARY_DB_URL) {
this.secondary = new PrismaClient({
datasources: { db: { url: process.env.SECONDARY_DB_URL } },
})
}
}
async executeQuery<T>(query: () => Promise<T>): Promise<T> {
if (this.isPrimaryHealthy) {
try {
return await query()
} catch (error) {
console.error('Primary DB failed, switching to secondary:', error)
this.isPrimaryHealthy = false
if (this.secondary) {
return await this.secondary.$transaction(async (tx) => {
return query.bind(this.secondary!)()
})
}
throw error
}
} else {
if (this.secondary) {
return await this.secondary.$transaction(async (tx) => {
return query.bind(this.secondary!)()
})
}
throw new Error('Both primary and secondary databases are unavailable')
}
}
}
连接监控和日志
启用查询日志
typescript
const prisma = new PrismaClient({
log: [
{ level: 'query', emit: 'event' }, // 记录所有查询
{ level: 'info', emit: 'stdout' }, // 信息日志
{ level: 'warn', emit: 'stdout' }, // 警告日志
{ level: 'error', emit: 'stdout' }, // 错误日志
],
})
// 监听查询事件
prisma.$on('query', (e) => {
console.log('Query: ' + e.query)
console.log('Params: ' + e.params)
console.log('Duration: ' + e.duration + 'ms')
})
性能监控
typescript
const prisma = new PrismaClient({
log: [
{
emit: 'event',
level: 'query',
},
],
})
// 查询性能监控
prisma.$on('query', (event) => {
if (event.duration > 1000) { // 记录超过 1 秒的查询
console.warn(`Slow query detected: ${event.query}`)
console.warn(`Duration: ${event.duration}ms`)
}
})
部署环境配置
Docker 环境
text
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# 在启动前生成 Prisma 客户端
RUN npx prisma generate
EXPOSE 3000
CMD ["npm", "start"]
Docker Compose 配置
yaml
# docker-compose.yml
version: '3.8'
services:
db:
image: postgres:14
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydb
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
app:
build: .
depends_on:
- db
environment:
DATABASE_URL: "postgresql://myuser:mypassword@db:5432/mydb"
ports:
- "3000:3000"
volumes:
postgres_data:
环境变量最佳实践
typescript
// config/database.ts
interface DatabaseConfig {
url: string
directUrl?: string
shadowDatabaseUrl?: string
}
export function getDatabaseConfig(): DatabaseConfig {
const config: DatabaseConfig = {
url: process.env.DATABASE_URL!,
}
if (process.env.DIRECT_DATABASE_URL) {
config.directUrl = process.env.DIRECT_DATABASE_URL
}
if (process.env.SHADOW_DATABASE_URL) {
config.shadowDatabaseUrl = process.env.SHADOW_DATABASE_URL
}
return config
}
// 使用配置
const dbConfig = getDatabaseConfig()
const prisma = new PrismaClient({
datasources: { db: dbConfig },
})
通过正确配置数据库连接,您可以确保应用程序能够可靠、安全地访问数据库,并具备适当的性能和容错能力。