数据库 Schema 设计 + 迁移包
10 件套,给真正负责数据库的工程师:DrawDB 画图、Atlas 声明式管理 schema、四款迁移工具(Liquibase / golang-migrate / dbmate / pgroll)覆盖各技术栈、Prisma + Drizzle 类型安全 ORM、Faker.js 造种子数据,再加一份零停机 expand-contract 清单。
这个包里有什么
受众:你是 orders 表迁移锁了 9 分钟时被叫醒的那个人。你设计 schema、写 ALTER TABLE、反向工程 2019 年别人留下的 Postgres、生成 ORM 类型让后端跟数据库别再漂移。AI agent 还是不擅长真实数据库相关的活——80 列的 schema、2 亿行的 events 表、没人记得为什么加上的外键。
这个包是 10 件套,专门补这个缺口。流程严格按顺序走:可视化 → 设计 → 迁移 → ORM → 种子 → (生产安全清单全程兜底)。 五个层次,每一层解锁下一层。
按这个顺序装
- DrawDB (id 2637) — 从这里开始。开源、浏览器内的 schema 关系图编辑器。粘贴
CREATE TABLEdump 出 ERD;画 ERD 出 DDL。用来反向工程已有数据库,在让 agent 动它之前先有图。Agent 看图比看 4000 行schema.sql准得多。 - Atlas (id 1702) — 声明层。你写目标 schema(HCL 或 SQL),Atlas 跟线上 DB diff 自动出迁移。支持 PostgreSQL、MySQL、SQLite、SQL Server、ClickHouse。包里最 agent-friendly 的工具:agent 改声明式
schema.hcl没问题,手写命令式ALTER链经常错。 - Liquibase (id 1894) — 企业级迁移层。XML / YAML / JSON / SQL changelog,带版本、可回滚、JDBC 全家桶。你出 Java、跨数据库、合规要求每条变更带 rollback 块 — 选它。
- golang-migrate (id 1696) — Go 原生迁移 CLI + 库。20+ 数据库驱动,纯 SQL up/down 文件,没 DSL 要学。跟任何 Go 服务搭配;CI 里就一个静态二进制。
- dbmate (id 1703) — 栈无关的另一选。单个 Go 二进制,纯 SQL,支持 PostgreSQL / MySQL / SQLite / ClickHouse。不出 Go 但想要一个二进制 CLI、不带 Node/Python/Ruby 依赖 — 选它而非 golang-migrate。
- pgroll (id 4100) — Postgres-only,零停机。自动实现 expand-and-contract:双写 schema、分批回填、切读、丢老列。你最怕的那次迁移(2 亿行表上重命名一列)就用它。
- 零停机迁移清单 (id 4264) — 方法论层。一份可复用的 agent 清单,把任何 expand-contract 迁移走完:加列、发版应用、回填、双读窗口、发版 contract、删老列。挂在 context 里,agent 就不会偷懒直接
ALTER。 - Prisma (id 992) — Node.js / TypeScript 的类型安全 ORM。Schema-first:
schema.prisma是真相源,prisma migrate生成 SQL,prisma generate出全类型 client。支持 PostgreSQL / MySQL / MariaDB / SQL Server / SQLite / MongoDB / CockroachDB。Agent 爱 Prisma —— 错误在编译期暴露,不是凌晨 3 点。 - Drizzle ORM (id 666) — 更轻的备选。TypeScript 原生、SQL 风格语法、零运行时开销、对 serverless 友好。包体积重要(edge、Workers、Lambda)或者你想写起来还像 SQL 的 SQL — 选 Drizzle 而非 Prisma。
- Faker.js (id 2137) — 种子层。在 JS/TS 里生成真实感的姓名、地址、邮箱、商品。喂给 ORM 的 seed 脚本,dev DB 立刻有 1 万条像样的数据,测试和 agent 的示例查询都不再像假货。
它们怎么串起来
┌─────────────────┐
│ DrawDB (2637) │ ← 反向工程已有 DB,
└────────┬────────┘ 或者画新 ERD
│
▼
┌─────────────────┐
│ Atlas (1702) │ ← 声明式目标 schema
└────────┬────────┘ 跟线上 diff → SQL
│
▼
┌────────────────┴───────────────────┐
│ 迁移执行器(选一个适配你的栈) │
│ Liquibase (1894) — Java / XML │
│ golang-migrate (1696) — Go │
│ dbmate (1703) — 单个二进制 │
│ pgroll (4100) — 零停机 Postgres │
└────────────────┬───────────────────┘
│
零停机清单 (4264)
守护每一次破坏性变更
│
▼
┌─────────────────┐
│ ORM (Node/TS) │
│ Prisma (992) │ ← schema-first,全类型 client
│ Drizzle (666) │ ← SQL-first,edge 就绪
└────────┬────────┘
│
▼
┌─────────────────┐
│ Faker.js (2137)│ ← 用真实感数据 seed dev DB
└─────────────────┘
关键回路:画出真相(DrawDB)→ 声明目标(Atlas)→ 安全迁移(Liquibase / golang-migrate / dbmate / pgroll,全程被 expand-contract 清单守护)→ 暴露类型化访问(Prisma 或 Drizzle)→ 种子可信数据(Faker.js)。 跳过声明层迁移就成命令式意大利面;跳过清单 agent 早晚会在生产 drop 一列。
你会撞到的权衡
- 声明式(Atlas)vs 命令式(golang-migrate / dbmate) — Atlas 帮你 diff,绿地项目、小团队很爽;命令式 SQL 文件给你完整控制权,等迁移里要嵌业务逻辑回填时才用得上。大多数团队两个都跑:常规变更 Atlas,复杂的手写。
- Liquibase vs golang-migrate / dbmate — Liquibase XML 味、JDBC 味、对审计友好;Go 系工具纯 SQL、单个二进制、对 CI 友好。合规要 rollback 元数据进版本控制 — 选 Liquibase;团队本能就是「给我
.sql文件」— 选 Go 系。 - pgroll vs 手写 expand-contract — pgroll 只自动化 Postgres 的双写模式。MySQL 或跨库就得自己跳这支舞,清单 4264 是剧本。别在 Liquibase 上面套 pgroll — 一次迁移选其一。
- Prisma vs Drizzle — Prisma 拥有 schema(
schema.prisma);Drizzle 要你自己拥有(在 TypeScript 里声明)。Prisma 对 AI agent 更友好 —— DSL 小且一致;Drizzle 对懂 SQL 的人更友好。两者都给迁移、都给类型 client。 - Faker.js vs 生产快照 — 假数据规避了拷贝生产行的法务风险。脱敏快照更真实但配起来要几周。先用 Faker,等碰到只在生产基数下才复现的 bug class 再升级到脱敏快照。
常见踩坑
- 让 agent 直接生成
DROP COLUMN— 永远走 expand-contract 清单(4264)。agent 会很乐意给你写一行迁移,把还被部署中二进制引用的列直接干掉。 - 同一个数据库上同时跑 pgroll 和通用迁移工具 — 它们各自写自己的 metadata 表,会打架。一个 DB 选一个。
- 在 DrawDB 里设计完忘了同步回 Atlas — 关系图不是真相源,声明式 schema 文件才是。从 DrawDB 导出,粘到
schema.hcl,之后别再改关系图。 - Faker 调一次就把结果 commit — Faker 默认非确定性。要 reproducible 测试数据就 seed 它(
faker.seed(42)),否则 CI 会因行数随机抖动而 flake。 - 在陌生数据库上跳过画图步骤 — agent 误读 4000 行
schema.sql。看 DrawDB ERD 第一遍准确率 80%。重构前永远先反向工程。
10 个资产打包就绪
常见问题
为啥没有 Postgres MCP server?
MCP server 们(PostgreSQL MCP、Postgres MCP Pro、DBHub、Supabase MCP)住在姐妹包「Postgres for AI Agents」和「后端工程师 AI 工具包」里,下面有内链。这个包是上游的那一段:MCP server 读到 schema 之前,schema 怎么设计、怎么迁移、怎么类型化。两个包一起装就是完整的数据层鞍具。
Atlas 或只用 Liquibase — 选一个?
不同层。Atlas 声明式(你写目标态,它 diff);Liquibase 命令式(你写变更,它记历史)。多数成熟团队 Atlas 当 schema-as-code 进版本控制,Liquibase 或 golang-migrate 当执行器在生产应用版本化的变更。它们组合用。小团队选其一也行;大多是加列加表 — 选 Atlas;审计要 rollback 元数据 — 选 Liquibase。
为啥四个迁移执行器 — 不过头了吗?
一个栈对一个:Liquibase 给 Java / 跨库 / 企业,golang-migrate 给 Go 店,dbmate 给单个二进制栈无关方案,pgroll 专门给零停机 Postgres。你装符合你现实那个就行。包里全列出来是为了 agent 按手上项目选对的那个,而不是默认用训练数据里最常见那个。
Prisma 或 Drizzle — 今天该选哪个?
Prisma — 想要严格的 schema-first DSL,agent 能安全编辑,生成的 client 编译期就拦住误用。Drizzle — 想要 SQL-first 的手感、edge/serverless 的小包体、零 ORM 运行时。两个都给迁移、都给类型。诚实划分:在意安全的应用团队 Prisma,在意控制的基建团队 Drizzle。
Faker 真能 seed 出生产级数据吗?
dev 和 CI 够用。压测或验证查询计划终归要脱敏后的生产快照 —— Faker 分布均匀,真实数据是长尾。折中:dev 用 Faker(快、无合规负担),staging 维护独立的脱敏快照管道,发版前在那里验查询计划。