Completed: - Add 6 core database documents (docs/01-平台基础层/07-数据库/) Architecture overview, migration history, environment comparison, tech debt tracking, seed data management, PostgreSQL extensions - Restructure deployment docs: archive 20 legacy files to _archive-2025/ - Create unified daily operations manual (01-日常更新操作手册.md) - Add pending deployment change tracker (03-待部署变更清单.md) - Update database development standard to v3.0 (three iron rules) - Fix Prisma schema type drift: align @db.* annotations with actual DB IIT: UUID/Timestamptz(6), SSA: Timestamp(6)/VarChar(20/50/100) - Add migration: 20260227_align_schema_with_db_types (idempotent ALTER) - Add Cursor Rule for auto-reminding deployment change documentation - Update system status guide v6.4 with deployment and DB doc references - Add architecture consultation docs (Prisma guide, SAE deployment guide) Technical details: - Manual migration due to shadow DB limitation (TD-001 in tech debt) - Deployment docs reduced from 20+ scattered files to 3 core documents - Cursor Rule triggers on schema.prisma, package.json, Dockerfile changes Made-with: Cursor
584 lines
18 KiB
Markdown
584 lines
18 KiB
Markdown
# 数据库开发规范
|
||
|
||
> 版本: v3.0
|
||
> 更新日期: 2026-02-27
|
||
> v3.0 更新: 新增部署变更实时记录规则、Shadow DB 降级方案、0227 事故教训
|
||
|
||
---
|
||
|
||
## 📢 核心原则
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 🎯 三条铁律 │
|
||
│ │
|
||
│ 1. ✅ 所有数据库变更必须通过 Prisma migrate 管理 │
|
||
│ 2. ✅ 变更同时必须记录到「待部署变更清单」 │
|
||
│ 3. ❌ 绝对禁止 prisma db push(除非你愿意花一天修 drift) │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 变更记录规则(v3.0 新增)
|
||
|
||
**每次修改 schema.prisma 并生成迁移后,立即做两件事**:
|
||
|
||
1. 提交迁移文件到 Git
|
||
2. 在 `docs/05-部署文档/03-待部署变更清单.md` 追加一行记录
|
||
|
||
```markdown
|
||
| DB-N | 简述变更 | `迁移文件名` | 高/中/低 | 备注 |
|
||
```
|
||
|
||
> Cursor Rule `.cursor/rules/deployment-change-tracking.mdc` 会在你修改 schema.prisma 时自动提醒。
|
||
|
||
---
|
||
|
||
## 1. 开发流程规范
|
||
|
||
### 1.1 标准开发流程(必须遵循)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 数据库变更标准流程 │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
|
||
开发阶段 部署阶段
|
||
──────── ────────
|
||
|
||
┌─────────────────┐ ┌─────────────────┐
|
||
│ 1. 修改 schema.prisma │ │ 1. 代码合并到主分支 │
|
||
└────────┬────────┘ └────────┬────────┘
|
||
│ │
|
||
▼ ▼
|
||
┌─────────────────┐ ┌─────────────────┐
|
||
│ 2. npx prisma migrate dev │ │ 2. 备份生产数据库 │
|
||
│ --name feature_name │ └────────┬────────┘
|
||
└────────┬────────┘ │
|
||
│ ▼
|
||
▼ ┌─────────────────┐
|
||
┌─────────────────┐ │ 3. npx prisma migrate deploy │
|
||
│ 3. 检查生成的迁移SQL │ └────────┬────────┘
|
||
└────────┬────────┘ │
|
||
│ ▼
|
||
▼ ┌─────────────────┐
|
||
┌─────────────────┐ │ 4. 验证 & 测试 │
|
||
│ 4. 本地测试 │ └─────────────────┘
|
||
└────────┬────────┘
|
||
│
|
||
▼
|
||
┌─────────────────┐
|
||
│ 5. 提交代码 + 迁移文件 │
|
||
└─────────────────┘
|
||
```
|
||
|
||
### 1.2 命令使用规范
|
||
|
||
| 场景 | 命令 | 说明 |
|
||
|------|------|------|
|
||
| **开发时新增/修改表** | `npx prisma migrate dev --name xxx` | ✅ 生成迁移文件 |
|
||
| **生产环境部署** | `npx prisma migrate deploy` | ✅ 应用未执行的迁移 |
|
||
| **生成 Prisma Client** | `npx prisma generate` | ✅ 更新类型定义 |
|
||
| **检查迁移状态** | `npx prisma migrate status` | ✅ 查看待迁移列表 |
|
||
| **验证 Schema** | `npx prisma validate` | ✅ 检查语法错误 |
|
||
|
||
### 1.3 禁止使用的命令
|
||
|
||
| 命令 | 危险等级 | 原因 |
|
||
|------|----------|------|
|
||
| `prisma db push` | 🟠 **高** | 不生成迁移文件,无法追踪变更历史 |
|
||
| `prisma db push --force-reset` | 🔴 **极高** | 会删除所有数据 |
|
||
| `prisma migrate reset` | 🔴 **极高** | 重置整个数据库 |
|
||
| 手工执行 `ALTER TABLE` | 🟠 **高** | 导致 Schema 与数据库不一致 |
|
||
| 手工执行 `CREATE TABLE` | 🟠 **高** | 导致 Schema 与数据库不一致 |
|
||
|
||
---
|
||
|
||
## 2. Schema 变更示例
|
||
|
||
### 2.1 新增表
|
||
|
||
```prisma
|
||
// 1. 在 schema.prisma 中添加模型
|
||
model NewFeature {
|
||
id String @id @default(uuid())
|
||
name String
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
@@map("new_features") // 表名使用下划线
|
||
@@schema("feature_schema") // 指定 Schema
|
||
}
|
||
```
|
||
|
||
```bash
|
||
# 2. 生成迁移
|
||
npx prisma migrate dev --name add_new_feature_table
|
||
|
||
# 3. 检查生成的 SQL
|
||
cat prisma/migrations/xxx_add_new_feature_table/migration.sql
|
||
```
|
||
|
||
### 2.2 新增字段
|
||
|
||
```prisma
|
||
// 1. 在模型中添加字段
|
||
model User {
|
||
id String @id
|
||
email String
|
||
phone String? // 新增字段,可为空
|
||
createdAt DateTime @default(now())
|
||
|
||
@@schema("platform_schema")
|
||
}
|
||
```
|
||
|
||
```bash
|
||
# 2. 生成迁移
|
||
npx prisma migrate dev --name add_user_phone_field
|
||
```
|
||
|
||
### 2.3 修改字段
|
||
|
||
```prisma
|
||
// 1. 修改字段类型或约束
|
||
model Document {
|
||
id String @id
|
||
title String @db.VarChar(500) // 修改长度
|
||
description String? @db.Text // 改为 Text 类型
|
||
|
||
@@schema("pkb_schema")
|
||
}
|
||
```
|
||
|
||
```bash
|
||
# 2. 生成迁移(注意:某些修改可能导致数据丢失)
|
||
npx prisma migrate dev --name update_document_fields
|
||
```
|
||
|
||
### 2.4 新增 Schema
|
||
|
||
```prisma
|
||
// 1. 在 datasource 中添加新 Schema
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
schemas = ["platform_schema", "aia_schema", "new_schema"] // 添加新 Schema
|
||
}
|
||
|
||
// 2. 创建使用新 Schema 的模型
|
||
model NewModule {
|
||
id String @id
|
||
name String
|
||
|
||
@@schema("new_schema")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 迁移文件管理
|
||
|
||
### 3.1 迁移文件结构
|
||
|
||
```
|
||
prisma/
|
||
├── schema.prisma # Schema 定义文件
|
||
├── migrations/
|
||
│ ├── 20251010075003_init/
|
||
│ │ └── migration.sql # 初始化迁移
|
||
│ ├── 20251012124747_add_batch/
|
||
│ │ └── migration.sql # 功能迁移
|
||
│ └── migration_lock.toml # 迁移锁文件
|
||
└── manual_sql_scripts/ # 手动 SQL(仅用于特殊场景)
|
||
└── *.sql
|
||
```
|
||
|
||
### 3.2 迁移文件命名规范
|
||
|
||
```bash
|
||
# 格式:动词_对象_描述
|
||
npx prisma migrate dev --name add_user_phone_field
|
||
npx prisma migrate dev --name create_iit_schema_tables
|
||
npx prisma migrate dev --name update_document_status_enum
|
||
npx prisma migrate dev --name remove_deprecated_columns
|
||
```
|
||
|
||
### 3.3 迁移文件版本控制
|
||
|
||
```
|
||
✅ 必须提交的文件:
|
||
- prisma/schema.prisma
|
||
- prisma/migrations/*/migration.sql
|
||
- prisma/migrations/migration_lock.toml
|
||
|
||
❌ 不要提交的文件:
|
||
- 本地测试的临时迁移
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 生产环境部署规范
|
||
|
||
### 4.1 部署前检查清单
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 📋 生产部署前检查清单 │
|
||
├─────────────────────────────────────────────────────────────────────┤
|
||
│ □ 本地开发环境测试通过 │
|
||
│ □ 迁移文件已提交到代码仓库 │
|
||
│ □ 已执行 npx prisma migrate status 确认待迁移列表 │
|
||
│ □ 已审查迁移 SQL,确认无破坏性变更 │
|
||
│ □ 已备份生产数据库 │
|
||
│ □ 已准备回滚方案 │
|
||
│ □ 已通知相关人员 │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 部署命令
|
||
|
||
```bash
|
||
# 1. 检查迁移状态
|
||
npx prisma migrate status
|
||
|
||
# 2. 执行迁移(仅应用未执行的迁移)
|
||
npx prisma migrate deploy
|
||
|
||
# 3. 生成 Prisma Client
|
||
npx prisma generate
|
||
```
|
||
|
||
### 4.3 SAE 环境部署
|
||
|
||
在 SAE 部署时,Dockerfile 中应包含:
|
||
|
||
```dockerfile
|
||
# 构建阶段
|
||
RUN npx prisma generate
|
||
|
||
# 启动命令(package.json 中配置)
|
||
# "start:prod": "npx prisma migrate deploy && node dist/main.js"
|
||
```
|
||
|
||
或在启动脚本中:
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# 应用迁移
|
||
npx prisma migrate deploy
|
||
|
||
# 启动应用
|
||
node dist/main.js
|
||
```
|
||
|
||
### 4.4 回滚方案
|
||
|
||
```bash
|
||
# 方案1:从备份恢复(推荐)
|
||
cat backup_before_migration.sql | docker exec -i ai-clinical-postgres psql -U postgres -d ai_clinical_research
|
||
|
||
# 方案2:手动回滚迁移(需要准备回滚 SQL)
|
||
# 在 migrations/ 目录下准备 rollback_xxx.sql
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 多 Schema 架构规范
|
||
|
||
### 5.1 当前 Schema 列表
|
||
|
||
> 完整的表级清单见 `docs/01-平台基础层/07-数据库/00-数据库架构总览.md`
|
||
|
||
| Schema | 用途 | 表数量 | 管理方式 |
|
||
|--------|------|--------|----------|
|
||
| `platform_schema` | 平台基础设施(用户、租户、pg-boss) | 19 | Prisma + pg-boss |
|
||
| `iit_schema` | IIT 临床试验管理 Agent | 20 | Prisma |
|
||
| `asl_schema` | AI 智能文献 | 11 | Prisma |
|
||
| `ssa_schema` | 智能统计分析 | 11 | Prisma |
|
||
| `dc_schema` | 数据清洗 | 6 | Prisma |
|
||
| `agent_schema` | 通用 Agent 框架 | 6 | Prisma |
|
||
| `pkb_schema` | 个人知识库 | 5 | Prisma |
|
||
| `capability_schema` | Prompt 管理 + 系统知识库 | 4 | Prisma |
|
||
| `aia_schema` | AI 智能问答 | 3 | Prisma |
|
||
| `ekb_schema` | 企业知识库(向量) | 3 | Prisma |
|
||
| `admin_schema` | 运营管理 | 2 | Prisma |
|
||
| `protocol_schema` | 方案 Agent | 2 | Prisma |
|
||
| `rvw_schema` | 稿件审查 | 1 | Prisma |
|
||
| `public` | 遗留 + Prisma 迁移表 | 3 | Prisma |
|
||
|
||
### 5.2 新增 Schema 规范
|
||
|
||
```prisma
|
||
// 1. 在 datasource 中声明
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
schemas = [
|
||
"platform_schema",
|
||
"aia_schema",
|
||
// ... 现有 schemas
|
||
"new_module_schema" // 新增
|
||
]
|
||
}
|
||
|
||
// 2. 在模型中使用
|
||
model NewModuleTable {
|
||
id String @id @default(uuid())
|
||
name String
|
||
|
||
@@map("new_module_tables")
|
||
@@schema("new_module_schema")
|
||
}
|
||
```
|
||
|
||
### 5.3 命名规范
|
||
|
||
| 类型 | 格式 | 示例 |
|
||
|------|------|------|
|
||
| Schema | `{module}_schema` | `iit_schema`, `asl_schema` |
|
||
| 表名 | `{module_prefix}_{entity_name}` | `dc_templates`, `asl_literatures` |
|
||
| 字段名 | `snake_case` | `created_at`, `user_id` |
|
||
| 索引名 | `idx_{table}_{column}` | `idx_users_email` |
|
||
|
||
---
|
||
|
||
## 6. 特殊场景处理
|
||
|
||
### 6.1 pg-boss 表(自动管理)
|
||
|
||
pg-boss 会自动创建和管理以下表,**不需要**在 Prisma Schema 中定义:
|
||
|
||
| 表名 | 用途 |
|
||
|------|------|
|
||
| `platform_schema.job` | 任务队列 |
|
||
| `platform_schema.job_common` | 任务通用信息 |
|
||
| `platform_schema.queue` | 队列定义 |
|
||
| `platform_schema.schedule` | 定时任务 |
|
||
| `platform_schema.subscription` | 订阅信息 |
|
||
| `platform_schema.version` | 版本信息 |
|
||
|
||
### 6.2 pgvector 字段
|
||
|
||
```prisma
|
||
// pgvector 类型使用 Unsupported
|
||
model EkbChunk {
|
||
id String @id
|
||
content String
|
||
embedding Unsupported("vector")? // 向量字段
|
||
|
||
@@schema("ekb_schema")
|
||
}
|
||
```
|
||
|
||
操作 vector 字段时使用原生 SQL:
|
||
|
||
```typescript
|
||
// 插入向量
|
||
await prisma.$executeRaw`
|
||
UPDATE ekb_schema.ekb_chunk
|
||
SET embedding = ${embedding}::vector
|
||
WHERE id = ${id}
|
||
`
|
||
|
||
// 相似度查询
|
||
const results = await prisma.$queryRaw`
|
||
SELECT id, content, 1 - (embedding <=> ${queryVector}::vector) as similarity
|
||
FROM ekb_schema.ekb_chunk
|
||
ORDER BY embedding <=> ${queryVector}::vector
|
||
LIMIT 10
|
||
`
|
||
```
|
||
|
||
### 6.3 从数据库同步 Schema(紧急情况)
|
||
|
||
仅在 Schema 与数据库严重不一致时使用:
|
||
|
||
```bash
|
||
# 1. 备份当前 Schema
|
||
cp prisma/schema.prisma prisma/schema.prisma.backup
|
||
|
||
# 2. 从数据库拉取
|
||
npx prisma db pull
|
||
|
||
# 3. 标记所有现有迁移为已应用
|
||
npx prisma migrate resolve --applied <migration_name>
|
||
|
||
# 4. 验证
|
||
npx prisma migrate status
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 备份规范
|
||
|
||
### 7.1 备份时机
|
||
|
||
| 时机 | 是否必须 | 备份方式 |
|
||
|------|----------|----------|
|
||
| 执行 `prisma migrate deploy` 前 | ✅ 必须 | 全量备份 |
|
||
| 重大功能发布前 | ✅ 必须 | 全量备份 |
|
||
| 每日自动备份 | ✅ 推荐 | 增量/全量 |
|
||
| 数据导入前 | ✅ 必须 | 全量备份 |
|
||
|
||
### 7.2 备份命令
|
||
|
||
```bash
|
||
# 本地 Docker 备份
|
||
docker exec ai-clinical-postgres pg_dump \
|
||
-U postgres \
|
||
-d ai_clinical_research \
|
||
--format=plain \
|
||
--no-owner \
|
||
--no-acl \
|
||
> backup_$(date +%Y%m%d_%H%M%S).sql
|
||
|
||
# RDS 备份(需要开启外网访问)
|
||
PGPASSWORD='xxx' pg_dump \
|
||
-h pgm-xxx.pg.rds.aliyuncs.com \
|
||
-p 5432 \
|
||
-U airesearch \
|
||
-d ai_clinical_research_test \
|
||
--format=plain \
|
||
--no-owner \
|
||
> rds_backup_$(date +%Y%m%d_%H%M%S).sql
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 常见问题
|
||
|
||
### 8.1 迁移冲突
|
||
|
||
```bash
|
||
# 问题:多人开发时迁移文件冲突
|
||
# 解决:
|
||
1. git pull 获取最新代码
|
||
2. npx prisma migrate status 查看状态
|
||
3. 如有冲突,手动合并迁移文件或重新生成
|
||
```
|
||
|
||
### 8.2 迁移失败回滚
|
||
|
||
```bash
|
||
# 问题:migrate deploy 失败
|
||
# 解决:
|
||
1. 从备份恢复数据库
|
||
2. 修复 schema.prisma
|
||
3. 重新生成迁移
|
||
4. 再次尝试部署
|
||
```
|
||
|
||
### 8.3 Schema 与数据库不一致
|
||
|
||
```bash
|
||
# 检查差异
|
||
npx prisma migrate diff \
|
||
--from-schema-datasource prisma/schema.prisma \
|
||
--to-schema-datamodel prisma/schema.prisma
|
||
|
||
# 如果需要重新同步
|
||
npx prisma db pull # 从数据库拉取
|
||
# 或
|
||
npx prisma migrate dev # 从 Schema 推送
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 检查清单
|
||
|
||
### 9.1 每次变更前
|
||
|
||
- [ ] 已从主分支更新代码
|
||
- [ ] 已运行 `npx prisma migrate status`
|
||
- [ ] 已备份本地数据库(重要数据)
|
||
|
||
### 9.2 每次变更后
|
||
|
||
- [ ] 迁移文件已生成
|
||
- [ ] 本地功能测试通过
|
||
- [ ] 已检查生成的迁移 SQL
|
||
- [ ] 已提交 schema.prisma 和迁移文件
|
||
|
||
### 9.3 生产部署时
|
||
|
||
- [ ] 已备份生产数据库
|
||
- [ ] 已在测试环境验证迁移
|
||
- [ ] 已准备回滚方案
|
||
- [ ] 已执行 `npx prisma migrate deploy`
|
||
- [ ] 已验证应用正常运行
|
||
|
||
---
|
||
|
||
## 10. Shadow DB 失败时的降级方案(v3.0 新增)
|
||
|
||
当 `prisma migrate dev` 因 Shadow DB 重放失败时(例如引用了 `db push` 创建的表),使用以下降级流程:
|
||
|
||
```bash
|
||
# 1. 手动创建迁移目录
|
||
mkdir prisma/migrations/YYYYMMDD_migration_name
|
||
|
||
# 2. 编写迁移 SQL(参考 prisma migrate diff 的输出)
|
||
npx prisma migrate diff \
|
||
--from-url "$DATABASE_URL" \
|
||
--to-schema-datamodel prisma/schema.prisma \
|
||
--script > prisma/migrations/YYYYMMDD_migration_name/migration.sql
|
||
|
||
# 3. 审查 SQL,确认无破坏性操作
|
||
|
||
# 4. 手动执行 SQL 到数据库
|
||
|
||
# 5. 标记为已应用
|
||
npx prisma migrate resolve --applied YYYYMMDD_migration_name
|
||
```
|
||
|
||
> 详见 `docs/01-平台基础层/07-数据库/03-技术债务追踪.md` TD-001
|
||
|
||
---
|
||
|
||
## 附录:历史事故
|
||
|
||
### 案例1:2026-01-11 数据库重置事故
|
||
|
||
**原因**:使用 `prisma db push --force-reset`
|
||
**影响**:pg-boss 函数丢失,用户数据丢失
|
||
**教训**:永远不要使用 `--force-reset`,操作前必须备份
|
||
|
||
### 案例2:手工 SQL 导致 Schema 不一致
|
||
|
||
**原因**:直接执行 `ALTER TABLE` 添加字段
|
||
**影响**:Prisma Schema 与数据库不一致,后续迁移失败
|
||
**教训**:所有变更必须通过 Prisma Schema
|
||
|
||
### 案例3:2026-02-27 prisma db push 引发的部署 drift(v3.0 新增)
|
||
|
||
**原因**:开发过程中大量使用 `prisma db push` 快速迭代,绕过了迁移系统
|
||
**影响**:
|
||
- 部署到测试环境时发现 6 张表 + 10 个列不在任何迁移文件中
|
||
- 部署后运行时报错 `column does not exist`(ssa_sessions.data_profile, review_tasks.context_data)
|
||
- 需要紧急编写 drift patch 迁移 + 线上热修 SQL
|
||
- Shadow DB 重放失败,`prisma migrate dev` 不可用
|
||
|
||
**修复耗时**:约 3 小时(drift 分析 + patch 编写 + 线上热修 + Schema 类型对齐)
|
||
**教训**:
|
||
1. `prisma db push` 是"技术债 ATM"——每用一次就欠一笔
|
||
2. 即使是快速原型,也应使用 `prisma migrate dev --create-only` 生成迁移后再审查执行
|
||
3. 变更后必须立即记录到 `03-待部署变更清单.md`
|
||
|
||
---
|
||
|
||
## 附录:相关文档索引
|
||
|
||
| 文档 | 位置 |
|
||
|------|------|
|
||
| 数据库架构全景(96 张表) | `docs/01-平台基础层/07-数据库/00-数据库架构总览.md` |
|
||
| 迁移历史(14 个迁移) | `docs/01-平台基础层/07-数据库/01-Prisma迁移历史与变更日志.md` |
|
||
| 环境差异对照 | `docs/01-平台基础层/07-数据库/02-环境状态对照表.md` |
|
||
| 技术债务追踪 | `docs/01-平台基础层/07-数据库/03-技术债务追踪.md` |
|
||
| 种子数据管理 | `docs/01-平台基础层/07-数据库/04-种子数据管理.md` |
|
||
| 待部署变更清单 | `docs/05-部署文档/03-待部署变更清单.md` |
|
||
|
||
---
|
||
|
||
> 📌 **记住**:Prisma Schema 是唯一真相来源(Single Source of Truth)
|
||
> 所有数据库结构变更必须先修改 Schema,再通过迁移应用到数据库
|
||
> **v3.0 补充**:变更后必须同步更新「待部署变更清单」,否则部署时一定会遗漏
|