ADR-0006:原型期用 SQLite 实现双库逻辑隔离,落地期换 PostgreSQL
- 状态:已采纳
- 日期:2026-09-15
- 决策者:毕设作者
- 相关文档:
docs/05-数据库设计.md、docs/adr/0001-dual-database-isolation.md
背景
ADR-0001 决定了"双库分离",但没决定用什么数据库引擎、隔离到什么程度。毕设的现实约束是:单人开发、一台开发机、无服务器采购预算、需要现场演示(可能没有网络)。
同时,答辩必然会被问:
你说的"双库分离",是两台物理数据库实例,还是逻辑分开?
这个问题如果回答含糊,会被认为没想清楚。
决策
分两阶段,同一套设计,只是隔离强度不同:
| 阶段 | business-db | ai-db | 隔离强度 |
|---|---|---|---|
| 原型期(毕设) | SQLite 单文件(如 data/business.sqlite) | SQLite + 向量扩展 / 或 Chroma 本地持久化目录 | 逻辑隔离:两套独立文件、独立进程、独立账号配置、独立备份策略 |
| 落地期(工业产品) | PostgreSQL 实例 | Qdrant / Chroma 独立实例 | 物理隔离:两台实例,可不同主机/网段 |
"逻辑隔离"在本项目中的精确定义(答辩时必须这样回答):
- 两套独立的数据库文件/实例,不是同一实例的两个 schema 共用连接;
- 两套完全独立的账号:
business-db账号只配置在业务接口服务与网关的进程中;ai-db账号只配置在网关的进程中; - Agent 进程中不存在任何一套的凭证;
- 两者的迁移脚本、种子数据、备份任务完全分开,互不引用。
理由
- 原型期用 SQLite 的收益:零运维、单文件、可随仓库演示、可直接用 SQL 工具打开截图作为答辩证据、无需网络。毕设验证的是架构与权限边界,不是数据库吞吐能力。
- 逻辑隔离已足以验证课题的核心命题。"Agent 拿不到业务库凭证"这件事,与数据库是否物理分离无关——只要 Agent 的环境变量里没有连接串,隔离就成立。物理分离提高的是故障域隔离强度与运维规范度,属于落地期收益。
- 设计可迁移。表结构、索引策略、字段白名单在 SQLite 与 PostgreSQL 之间基本可平移,迁移成本集中在 DDL 方言与并发控制,不影响 ADR-0001 的结论。
备选方案与拒绝理由
| 方案 | 为什么没选 |
|---|---|
| 原型期直接上 PostgreSQL | 需要安装、起服务、配账号、管理连接池,对单机演示是纯负担;毕设答辩价值不增。 |
| 原型期直接上两套 Docker 实例做物理隔离 | 演示环境依赖 Docker,现场风险高;且"逻辑隔离已足够"这一点反而讲不清楚。 |
| 用 MySQL + 向量插件凑成"单实例双库" | 两库共用同一实例 ⇒ 共用连接池与凭据管理路径,隔离论证变弱,得不偿失。 |
| 只用一个 SQLite 文件 + 表名前缀区分 | 最省事,但"双库分离"退化成命名约定,隔离完全靠代码自律,无法支撑答辩论证。 |
后果
正面
- 演示环境零依赖,仓库克隆即可跑通全链路。
- 双库的物理位置清晰可指(两个文件路径),答辩时可直接打开两个文件对比表结构,直观证明"ai-db 里没有任何业务字段"。
- 迁移到 PostgreSQL 时,ADR-0001 与 ADR-0002 的结论不变,只需重跑迁移脚本。
负面 / 代价
- SQLite 的并发写能力弱(单写者),遥测高频写入时会成为瓶颈。原型期通过批量写入 + WAL 模式缓解,并明确标注这是原型局限。
- SQLite 无行级安全策略(RLS)、无原生角色权限体系,"账号分离"退化为"连接串分离 + 文件系统权限分离",隔离强度弱于 PostgreSQL。此差异必须在
docs/05-数据库设计.md中显式标注,不能含糊带过。 - 向量检索需要额外选型:SQLite 无原生向量索引,原型期用 Chroma 本地持久化更省事(见
docs/05-数据库设计.md)。
明确写入文档的局限说明
原型期的 SQLite 双库方案,其隔离强度依赖文件系统权限 + 进程凭证分离,不具备数据库层的强制访问控制。若同机存在具有文件系统读权限的恶意进程,隔离可被绕过。落地期迁移至 PostgreSQL 后,由数据库角色权限(
GRANT/REVOKE)与可选的 RLS 提供强制约束。
这段话应原样出现在 docs/05-数据库设计.md 的"局限与风险"章节,答辩时主动说明。