Files
lingxi/docs/工程规范/05-数据库规范.md
T
Stev_Wang 00ae12435e docs(specs): add AGENTS.md and engineering guidelines
项目尚无统一工程规范,AI 助手与研发各自发挥导致返工风险。建立
总纲 + 细则两层结构:AGENTS.md 只写硬约束与索引(14 条红线、技术栈
基线、仓库结构、命令契约),细则拆为 10 份文档覆盖 Git、代码风格、
格式化、API 与路由、数据库、测试与 CI、Review、日志、密钥、资产命名。

影响面:仅文档。约束力从本轮起对新建代码生效;与现状冲突处以文档为准。
回滚方式:git revert 本提交。
2026-11-02 15:09:51 +08:00

6.4 KiB
Raw Blame History

05 · 数据库规范

项 内容
文档版本 V1.0(2026-11-02)
依据 技术架构 §5(数据模型)、§8.3 / §8.4(ADR)
适用范围 prisma/、所有 SQL、数据迁移脚本
强制级别 强制

1 命名与主键

对象 规则 示例
表 复数 snake_case media_tasks、brief_card_index
列 snake_case customer_id、created_at
主键 id,应用侧生成 ULID,char(26) 01JA8Z...
外键 <单数实体>_id script_id、customer_id
布尔 is_ / has_ 前缀 is_archived
时间 _at 后缀,timestamptz reviewed_at
金额 / 成本 _cost、_amount,numeric(18,6) unit_cost
JSON _json 或语义名(params、snapshot) output_params
索引 idx_<表>_<列>;唯一 uq_*;部分 idx_*_partial idx_media_tasks_customer_created
  • DB-01 禁止库内生成主键(不用 gen_random_uuid() / uuidv7());主键统一由应用生成 ULID,便于排序与分片。
  • DB-02 每张业务表必须含 created_at、updated_at;需要软删的加 deleted_at。
  • DB-03 Prisma 模型用 PascalCase + @@map / @map 映射到 snake_case,禁止直接在库里用 camelCase 列名。

2 客户隔离(最高优先级)

  • DB-04 所有业务表 customer_id NOT NULL + 外键;同时冗余 industry_id 便于按行业聚合。
  • DB-05 Repository 方法必须接收 ScopeContext 并在 where 中注入 customer_id;禁止「先查全量再在内存过滤」(PRD R-04)。
  • DB-06 唯一约束必须包含 customer_id(如客户内脚本编号唯一),跨客户唯一只允许编码类字段。
  • DB-07 跨客户写操作(跨客户复用授权)必须走显式授权表并写审计,禁止在业务 SQL 里放宽 customer_id。
  • DB-08 P1 起启用 PG 行级安全(RLS)兜底;启用前必须在 staging 验证「范围外查询返回 0 行」。

3 字段与类型

场景 规则
枚举 优先字典表 + 数据行;表内保存 *_snapshot(名称快照),避免字典变更影响历史
Prisma enum 仅用于永不扩展的封闭集合,且需迁移评审说明
动态字段 JSONB + schema_version;可检索字段物化到 brief_card_index(D-03)
大文本 text;禁止 varchar(255) 装富文本
时长 毫秒整数(duration_ms),禁止小数秒
比例 numeric(6,4);禁止 float 存比率
标签 关联表或 text[](仅查询简单场景);禁止 JSONB 存关联 ID(PRD R-25)
文件 只存对象存储 key(storage_key)+ 元数据,禁止存二进制或外链签名 URL
密码 / 密钥 只存哈希 / 密文;AI 供应商密钥用 AES-256-GCM 加密列
  • DB-09 JSONB 上默认不建 GIN 索引;仅在确有按字段查询且 EXPLAIN 证明需要时建。
  • DB-10 禁止 SELECT * 返回含大 JSONB 的列表;查询必须显式 select。

4 索引与查询

  • DB-11 所有外键列建索引。
  • DB-12 列表页统一复合索引:(customer_id, created_at DESC, id DESC);游标分页基于 (created_at, id)(技术架构 §5.7)。
  • DB-13 唯一约束配合软删用部分索引:WHERE deleted_at IS NULL。
  • DB-14 禁止无条件的 COUNT(*) 大表统计;计数走预聚合表或 EXPLAIN 验证代价。
  • DB-15 禁止 OFFSET 深翻页;分页一律游标。
  • DB-16 禁止 N+1:列表查询用 include/select 显式取关联,或批量 IN 查询。
  • DB-17 批量写入单批 ≤ 1000 行,超出分片;createMany 需注意不触发单条钩子。
  • DB-18 慢查询(> 200ms)必须记录到日志并带 trace_id,纳入每周巡检。

5 迁移(Prisma Migrate)

  • DB-19 迁移文件命名 YYYYMMDDHHmmss_<动词>_<对象>,如 20261102153000_add_material_specs。
  • DB-20 禁止修改已合并的迁移文件;修正用新迁移。
  • DB-21 采用 expand → migrate → contract 三步;禁止同一次发布内「删字段 + 改代码」(技术架构 §4.6)。
  • DB-22 生产迁移必须幂等、可重入;大表加列用可空列或带默认值的在线加列,禁止锁表长事务。
  • DB-23 迁移前必须备份,并在 staging 演练;回滚脚本随迁移一起提交(down 说明)。
  • DB-24 prisma db push 仅限本地探索,禁止用于任何共享环境。
  • DB-25 迁移涉及数据回填时,回填脚本独立于 schema 迁移,可重复执行。

6 事务与并发

  • DB-26 事务边界在 Service 层;跨表写必须同事务。
  • DB-27 事务内禁止外部 IO(AI 调用、HTTP、对象存储、ffmpeg)。
  • DB-28 编号 / 序号类唯一值(脚本编号、批次号)必须用原子取号(UPDATE ... RETURNING 或序列表 + 行锁),禁止「先查后写」。
  • DB-29 状态迁移用条件更新(WHERE status = 'pending')避免并发覆盖;受影响行数为 0 视为冲突并返回 409。
  • DB-30 避免长事务(> 5s);批量任务状态更新按批提交。

7 删除与保留

数据 策略
业务实体 软删 deleted_at;被引用的资产只能停用不能删除(PRD R-02)
审计 / 账本 / 任务事件 append-only,禁止 UPDATE / DELETE
任务临时产物 temp 桶 30 天自动清理
导出包 exports 桶 3 天
归档 archive 桶 ≥ 12 个月
客户数据删除 只按 PRD 约定的保留期与流程执行,禁止开发者自行清理
  • DB-31 硬删只允许:临时文件、失败任务产物、测试数据;且必须有清理任务与日志。
  • DB-32 审计表权限:应用账号仅 INSERT + SELECT,无 UPDATE / DELETE 授权。

8 检查清单

  • 表 / 列 snake_case,主键 ULID,created_at / updated_at 齐全
  • 业务表有 customer_id + 外键 + 冗余 industry_id
  • Repository 接收 ScopeContext,SQL 带客户维度
  • 列表查询走复合索引 + 游标分页,无 SELECT *、无 N+1
  • 迁移 expand/contract,未改历史迁移,staging 已演练
  • 事务内无外部 IO;编号原子取号;状态迁移带条件
  • 审计 append-only;临时产物有清理策略
  • 新增 JSONB 字段有 schema_version 与检索策略