跳到主要内容

数据库连接与连接池

问题

什么是数据库连接池?Serverless 场景下连接管理有什么问题?

答案

为什么需要连接池

每个数据库连接需要 TCP 握手、认证、分配内存。频繁创建销毁连接开销很大。

连接池配置

connection-pool.ts
// Prisma 连接池
const prisma = new PrismaClient({
datasources: {
db: {
url: `${process.env.DATABASE_URL}?connection_limit=20&pool_timeout=10`,
},
},
});

// TypeORM 连接池
const dataSource = new DataSource({
type: 'postgres',
host: 'localhost',
port: 5432,
extra: {
max: 20, // 最大连接数
min: 5, // 最小连接数
idleTimeoutMillis: 30000, // 空闲连接超时
connectionTimeoutMillis: 5000, // 连接超时
},
});

// node-postgres 原生连接池
import { Pool } from 'pg';
const pool = new Pool({
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
});

连接池大小计算

连接数=CPU 核心数×2+有效磁盘数\text{连接数} = \text{CPU 核心数} \times 2 + \text{有效磁盘数}

经验公式:对于大多数应用,10-20 个连接足以处理数千 QPS。

常见误区

连接池越大越好?。数据库总连接数有限(MySQL 默认 151),过多连接导致上下文切换开销增大,性能反而下降。

Serverless 连接问题

serverless-db.ts
// Neon Serverless Driver(HTTP/WebSocket)
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);

// 无需连接池,每次都是 HTTP 请求
const users = await sql`SELECT * FROM users WHERE id = ${userId}`;

// Prisma Accelerate(连接池代理服务)
const prisma = new PrismaClient({
datasources: {
db: { url: process.env.PRISMA_ACCELERATE_URL },
},
});

常见面试问题

Q1: 连接池满了怎么办?

答案

  1. 排查:是否有连接泄漏(未释放)
  2. 优化:减少查询耗时,快速归还连接
  3. 扩容:适当增大连接池
  4. 降级:设置请求排队超时,超时返回错误

Q2: 连接泄漏怎么排查?

答案

// 检查活跃连接数
// PostgreSQL
SELECT count(*) FROM pg_stat_activity;

// MySQL
SHOW PROCESSLIST;

常见原因:事务未提交/回滚、未使用 try/finally 释放连接。

Q3: Serverless 场景下的数据库选型?

答案

方案说明
NeonServerless PostgreSQL,自动扩缩容
PlanetScaleServerless MySQL(基于 Vitess)
Turso边缘 SQLite
SupabasePostgreSQL + 连接池
Prisma Accelerate连接池代理

相关链接