Macro数据库设计全解:Postgres + sqlx编译时检查 + 297个迁移文件
2026/9/16 13:35:42 网站建设 项目流程

Macro数据库设计全解:Postgres + sqlx编译时检查 + 297个迁移文件

【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — @-linked together with shared AI memory.项目地址: https://gitcode.com/GitHub_Trending/macro3/macro

Macro 是一个面向团队的统一工作区,把邮件、聊天、文档、任务、AI 智能体、通话和 CRM通过 @ 引用关联在一起,并共享同一份 AI 记忆。支撑这一切的,是一套以Postgres 为核心的数据库设计:全部核心数据落在一个由 macro_db_client 管理的数据库中,使用sqlx 编译时 SQL 检查,并通过300 多个迁移文件(当前 338 个)可追溯地演进 schema。本文将带你从架构到日常开发命令,完整看懂这套设计。

为什么统一工作区选择单一 Postgres

Macro 的产品形态决定了数据必须"互相认识":一封邮件可以 @ 一个文档,一个任务可以引用一条消息,一个 CRM 客户可以关联整段沟通历史。这种强关联场景下,跨库查询和一致性成本会急剧上升,而单一 Postgres 数据库配合清晰的域划分,是更简单也更可靠的选择。

从产品界面就能看出"数据互相 @ 关联"的设计:邮件线程、消息频道、任务清单、CRM 看板都不是孤立的功能,而是同一批实体(联系人、文档、消息、AI 记忆)在不同视角下的呈现。

Macro 数据库架构:macro_db_client 的域分离设计

Macro 的数据库访问层遵循"一个域、一个客户端 crate"的原则:

  • 核心业务库:crates/macro_db_client/ 负责 MacroDB 的全部查询,其 README 明确写着 "This crate handles all database queries for Macro DB"。它的 src/ 目录按域拆分为 email、chat、document、call、notification、organization 等 200 多个模块,每个模块对应一张或一组业务表。
  • 辅助库各自独立:邮件、通知、通讯录等重业务域还有专属客户端,如 email_db_client、notification_db_client、comms_db_client,各管各的表,互不干扰。
  • 模型层与存储层解耦:数据结构定义在 model、models_properties 等 crate 中,与执行 SQL 的 repo 层分离,方便测试与复用。

这种划分的直接好处:改邮件模块的查询,不会误碰通知模块的表;每个域的迁移脚本也随域走,责任清晰。

编译时 SQL 检查:让 SQL 错误在 cargo build 时暴露

传统 Rust 项目写 SQL 是"运行时惊喜":拼错表名、列类型不匹配,代码编译通过,到生产环境才报错。Macro 的做法是用sqlx 宏(Cargo.toml 中统一声明sqlx 0.8.6,启用postgreschronouuid特性):

  • query!query_as!query_scalar!query_file!这组宏在编译期连接数据库 schema 校验 SQL——表名不存在、列类型不符、参数个数不对,直接编译失败;
  • 整个 workspace 的查询元数据缓存在根目录的.sqlx/中(约 1700 个 query 元数据文件),离线构建时依然可用;
  • 官方文档 docs/DATABASE_DEVELOPMENT.md 明确要求"默认使用编译期检查宏,动态 SQL 仅限真正动态的场景,且动态标识符必须走白名单"。

对新手来说这意味着一件事:你在编辑器里保存的那一刻,SQL 是否写错就已经有答案了。这正是 Macro 在 200 多个 repo 模块中保持查询质量的关键。

300+ 迁移文件:schema 演进的完整历史

打开 crates/macro_db_client/migrations/,你会看到 338 个.sql迁移文件(另有若干服务的独立 migrations 目录,全仓库合计 348 个),全部用时间戳前缀命名,例如:

  • 0001_baseline.sql:1500 多行的基线迁移,包含 79 张核心表,文件头注释说明了它是"从 Prisma 迁移到 sqlx 时的基线,只在空库上执行";
  • 日常迁移如20251204165917_create_document_task_table.sql20260910144342_frecency_events_unprocessed_id_index.sql,一个文件只做一件事,文件名即变更说明。

全量迁移累计执行了 219 个CREATE TABLE。这套"每变更一步、必留痕"的机制,配合 tooling/just/sqlx.just 中封装的sqlx migrate run/sqlx migrate info命令,让任何一个历史节点上的 schema 都能被复现和审计。

新手注意:文档明确要求迁移文件只能由sqlx migrate add生成,禁止手写——因为手写文件容易猜错表名列名(schema 采用 camelCase 标识符,如"userId",查询时还需SELECT "userId" AS user_id做别名对齐),工具生成才能保证与真实 schema 一致。

来自开发指南的三条安全变更铁律

docs/DATABASE_DEVELOPMENT.md 中"Safe database schema changes"一节值得每个后端新人抄在便签上:

  1. 迁移先于服务上线——每个迁移必须兼容当前线上正在跑的服务代码,而不是你 PR 里的新代码;
  2. 删列必须分两步——先在服务 PR 中移除该列的所有读写,等全量部署完成后,再在另一个 PR里删列;删表、改列名同理;
  3. 新增列要宽容——在写入方迁移完成前,新列必须允许空值或带默认值,避免旧代码写入失败。

这三条的本质是:数据库是共享契约,任何破坏性变更都要给旧代码留一条活路

本地开发快速上手:三条命令跑起数据库

依托 justfile 和 docs/RUNNING_LOCALLY.md,本地环境搭建非常直接:

  1. just run_dbs -d——启动 Postgres 和 Redis 容器及网络;
  2. just setup_macrodb——创建 MacroDB 并应用全部迁移(含 README 中提到的测试前置条件);
  3. just crates/macro_db_client/migrate_db——后续每次 schema 变更后重新应用迁移。

当你修改了 SQL 或 schema,还需要刷新 sqlx 查询缓存:nix develop --command just prepare_db(内部调用cargo sqlx prepare --workspace)。缓存文件要随代码一起提交,但严禁手改.sqlx/query-*.json。遇到缓存缺失或 schema 漂移的报错,文档的 Troubleshooting 一节给了逐条排查路径。

总结

Macro 的数据库设计可以浓缩成三句话:

  • 一个 Postgres 支撑统一工作区,用"域分离"的 crate 结构控制复杂度;
  • sqlx 编译时检查把 SQL 错误拦在构建阶段,.sqlx缓存让离线开发成为可能;
  • 338 个可追溯的迁移文件 + 两条 PR 的破坏性变更纪律,让 schema 演进既有历史可查,又始终向后兼容。

这套实践不依赖任何宏大框架,而是"简单工具 + 严格纪律"的典范,非常值得正在做 Rust + Postgres 项目的团队参考。

【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — @-linked together with shared AI memory.项目地址: https://gitcode.com/GitHub_Trending/macro3/macro

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询