更新时间:2025-09-07
本文档给出从 Cloudflare D1 (SQLite) 迁移数据到 PostgreSQL 的示例流程与脚本。
1. 总体流程
- 导出 D1 数据:从 Cloudflare D1 导出 CSV/NDJSON 文件。
- 建 PG Schema:使用兼容的 Schema(UUID/ULID 主键、BIGINT 时间戳、TEXT JSON 等)。
- 导入 PG:使用
psql \copy
或脚本批量导入。 - 校验:行数校验、主键唯一性、抽样哈希校验。
- 切换应用:更改 Drizzle ORM 数据源 → Postgres。
2. 导出 D1 数据
Cloudflare Wrangler 提供导出工具:
bash
12345
# 导出整个数据库为 SQLite 文件
wrangler d1 export guess_db --local --output=backup.sqlite
# 或者导出为 SQL dump
wrangler d1 export guess_db --output=backup.sql
如果需要 CSV:
bash
1234
sqlite3 backup.sqlite \
-header -csv "SELECT * FROM users;" > users.csv
sqlite3 backup.sqlite \
-header -csv "SELECT * FROM sessions;" > sessions.csv
3. PostgreSQL 建表
示例(users):
sql
12345678
CREATE TABLE users (
id TEXT PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
is_admin INTEGER NOT NULL DEFAULT 0,
created_at BIGINT NOT NULL,
last_active_at BIGINT
);
完整表结构见 db-compatibility.md
。
4. 导入 PG
使用 psql \copy
:
bash
12345
\copy users(id,username,password_hash,is_admin,created_at,last_active_at) \
FROM 'users.csv' DELIMITER ',' CSV HEADER;
\copy sessions(id,status,host_username,started_at,ended_at) \
FROM 'sessions.csv' DELIMITER ',' CSV HEADER;
或用 pgloader
(支持 SQLite → PG 直接迁移):
lisp
12345
LOAD DATABASE
FROM sqlite:///backup.sqlite
INTO postgresql://user:pass@localhost:5432/mydb
WITH include drop, create tables, create indexes, reset sequences;
5. 校验
- 行数:确认表记录数一致。
- 约束:检查主键、唯一索引。
- 抽样:对比用户哈希或时间戳,确认一致。
6. 应用切换
Drizzle ORM 切换:
ts
12345678910
// D1
import { drizzle as drizzleD1 } from "drizzle-orm/d1";
const db = drizzleD1(env.DB);
// PostgreSQL
import { drizzle as drizzlePg } from "drizzle-orm/node-postgres";
import { Client } from "pg";
const pg = new Client({ connectionString: process.env.DATABASE_URL });
await pg.connect();
const db = drizzlePg(pg);
业务层(Repository/Service)无需修改。
7. 建议
- 小规模数据:CSV 导出/导入足够。
- 大规模数据:用
pgloader
,能自动建表并迁移索引。 - 迁移前建议在测试库跑一遍,确认 Schema & 数据一致。
8. 总结
- 导出 → 导入 → 校验 → 切换。
- 推荐
pgloader
做全量迁移。 - 应用层只需改 Drizzle 数据源,业务逻辑不变。