D1 导出成 SQLite:备份链路怎么走通
AI 摘要
D1 作为 SQLite 方言,导出标准 SQL 方便迁移。文章给出了导出命令、反向导入方法,以及三个关键坑:漏写 remote 会拿到空文件、缺少事务包装导致大表导入极慢、ALTER TABLE 能力有限需通过建表迁移绕过。最后演示了配合 GitHub Actions 实现自动化备份的方案。
D1 是 SQLite 的方言,所以导出的是标准 SQL——这让它成为整个 Cloudflare 体系里最好迁移的一环。
导出
npx wrangler d1 export wotw-db --remote --output=./database/backup/2026-09-01.sql
拿到的文件是完整的 CREATE TABLE + INSERT 语句,可以直接喂给 sqlite:
sqlite3 restored.db < 2026-09-01.sql
验证一下:
sqlite3 restored.db "SELECT COUNT(*) FROM comments;"
反向:SQLite 导入 D1
npx wrangler d1 execute wotw-db --remote --file=./database.sql
注意 D1 单次执行的语句大小有上限(默认几 MB),大表要分文件。
坑
1. --remote 不能漏。
不加 --remote 会导出本地开发数据库(.wrangler/state/ 下那个),通常是空的或者只有测试数据。我第一次备份就拿到了一个 0 字节的文件,还以为备份成功了。
2. 导出的 SQL 里没有 BEGIN/COMMIT。
大文件导入到 sqlite 时会很慢,因为每条 INSERT 都单独开事务。手动包一层:
(echo "BEGIN;"; cat 2026-09-01.sql; echo "COMMIT;") | sqlite3 restored.db
20 万行的表从 40 秒降到 1.5 秒。
3. D1 的 ALTER TABLE 支持有限。
D1 基于 SQLite,所以不支持 DROP COLUMN、ALTER COLUMN。改表只能:建新表 → 搬数据 → 删旧表 → 重命名。这也是为什么所有 schema 变更都必须走 migration 文件,不能线上手改(AI-RULE-008)。
自动化
备份脚本放在 scripts/export-db.ts,配 GitHub Actions 每周跑一次,产物推到私有仓库:
# .github/workflows/backup.yml
- run: npm run db:export
- run: |
git add database/backup/
git commit -m "chore: db backup $(date -u +%Y-%m-%d)"
git push
数据库备份推到第二个 Git remote,不让 GitHub 成为唯一备份点。
这是一条笔记,不是成稿文章。它可能不完整、可能有错,也可能过段时间就被我推翻。 想看成体系的文章,去 Blog。