Cloudflare Workers + D1:零成本搭建无服务器数据库
还在为个人项目的数据库费用发愁?
今天带你用 Cloudflare 的 D1 数据库,搭配 Workers 构建一个完全免费的无服务器后端!D1 是基于 SQLite 的关系型数据库,零配置、自动扩展,而且有慷慨的免费额度。
D1 是什么?
D1 是 Cloudflare 推出的无服务器关系型数据库,基于 SQLite 构建。它和 Workers、Pages、R2 等产品深度集成,让你可以用纯 JavaScript/TypeScript 操作数据库。
核心特性
| 特性 | 说明 |
|------|------|
| 引擎 | SQLite(轻量、可靠) |
| 读写 | Workers 内直接调用,延迟极低 |
| 备份 | 自动备份与时间点恢复 |
| 免费额度 | 5 GB 存储 + 500 万行读取/月 |
| 计费方式 | 按实际使用量付费,超出后也很便宜 |
适合场景
环境准备
前置条件
安装 wrangler
npm install -g wrangler登录 Cloudflare
wrangler login浏览器会打开授权页面,登录你的 Cloudflare 账号即可。
创建项目
初始化 Workers 项目
npx create-cloudflare my-app --type javascript
cd my-app创建 D1 数据库
# 创建数据库
wrangler d1 create my-database执行后会输出数据库 ID,类似:
✅ Successfully created DB 'my-database'
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"配置 wrangler.toml
将输出的配置添加到 wrangler.toml:
name = "my-app"
main = "src/index.js"
compatibility_date = "2025-12-01"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"建表与数据操作
创建表结构
创建一个 schema.sql 文件:
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);初始化数据库
wrangler d1 execute my-database --file=schema.sql编写 Worker
在 src/index.js 中:
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/users' && request.method === 'GET') {
const { results } = await env.DB.prepare(
'SELECT * FROM users ORDER BY created_at DESC'
).all();
return Response.json(results);
}
if (url.pathname === '/api/users' && request.method === 'POST') {
const { name, email } = await request.json();
const { success } = await env.DB.prepare(
'INSERT INTO users (name, email) VALUES (?, ?)'
).bind(name, email).run();
return Response.json({ success });
}
if (url.pathname.startsWith('/api/users/') && request.method === 'GET') {
const id = url.pathname.split('/')[3];
const user = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(id).first();
return Response.json(user || { error: 'not found' });
}
return new Response('D1 API is running!');
}
};部署
wrangler deploy进阶技巧
1. 参数化查询(防 SQL 注入)
始终使用 ? 占位符和 .bind() 来传递参数:
// 正确做法
const { results } = await env.DB.prepare(
'SELECT * FROM posts WHERE user_id = ? AND status = ?'
).bind(userId, 'published').all();
// 错误做法(不要拼接字符串)
const { results } = await env.DB.prepare(
`SELECT * FROM posts WHERE user_id = ${userId}` // ❌ SQL 注入风险
).all();2. 批量插入
const stmt = env.DB.prepare(
'INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)'
);
const batch = posts.map(post =>
stmt.bind(post.user_id, post.title, post.content)
);
const result = await env.DB.batch(batch);3. 事务处理
const result = await env.DB.batch([
env.DB.prepare('UPDATE users SET posts_count = posts_count + 1 WHERE id = ?').bind(userId),
env.DB.prepare('INSERT INTO posts (user_id, title) VALUES (?, ?)').bind(userId, title)
]);4. 读取复制(Read Replication)
D1 自动将数据复制到全球多个节点,读取操作会从最近的副本返回数据,延迟极低:
// 默认就是读取最近的副本
const { results } = await env.DB.prepare('SELECT * FROM posts').all();本地开发
使用 wrangler 的本地开发模式,不需要部署就能调试:
wrangler dev --local --persist--persist 参数会让数据持久化到本地磁盘,重启后数据还在。
与 Workers + Hono 组合
使用 Hono 框架可以让路由更优雅:
import { Hono } from 'hono';
const app = new Hono();
app.get('/api/posts', async (c) => {
const { results } = await c.env.DB.prepare(
'SELECT * FROM posts ORDER BY created_at DESC LIMIT 20'
).all();
return c.json(results);
});
app.post('/api/posts', async (c) => {
const body = await c.req.json();
const { success } = await c.env.DB.prepare(
'INSERT INTO posts (title, content) VALUES (?, ?)'
).bind(body.title, body.content).run();
return c.json({ success });
});
export default app;免费额度计算
D1 的免费额度对个人项目来说非常充足:
| 资源 | 免费额度 | 个人博客月消耗(估算) |
|------|---------|----------------------|
| 存储 | 5 GB | 50-100 MB |
| 读取行数 | 500 万/月 | 5-20 万 |
| 写入行数 | 10 万/月 | 1-5 万 |
即使超出,价格也很低:每额外 100 万行读取仅 $0.001。
常见问题
Q: D1 和 KV 有什么区别?
KV 是键值存储,适合简单读写、缓存场景。D1 是关系型数据库,支持 SQL 查询、联表、事务。需要复杂查询就用 D1,只存简单配置就用 KV。
Q: D1 支持外键吗?
支持。在创建表时定义 FOREIGN KEY 约束即可。
Q: 数据会丢失吗?
不会。D1 每天自动备份,支持时间点恢复(Point-in-Time Recovery)。
Q: 可以用 Prisma 吗?
可以。D1 支持 Prisma ORM,官方有集成方案。通过 wrangler d1 export 和 prisma migrate 配合使用。
总结
Cloudflare D1 让无服务器数据库变得前所未有的简单:
如果你正在做一个新项目,不妨试试 D1 —— 它可能就是你一直在找的数据库方案。
推荐指数:⭐⭐⭐⭐⭐
官方文档:https://developers.cloudflare.com/d1/
💬 评论区 (0)
暂无评论,快来抢沙发吧!