数据模型扩展.md 13 KB

数据模型扩展

本文引用的文件

  • schema.prisma
  • index.ts
  • book-generator.store.ts
  • stage-manager.ts
  • migrate-genstage.ts
  • sync-genstage.ts
  • database-structure.md
  • package.json

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构概览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向AI有声书生成平台的数据模型扩展需求,系统化说明如何基于Prisma ORM进行实体关系设计、字段定义与约束变更;解释迁移管理与版本控制策略;提供新增表、索引优化与查询性能调优的实践指南;阐述数据模型演进、向后兼容与数据迁移的最佳实践,并覆盖数据验证、事务处理与并发控制的实现方法。

项目结构

围绕数据模型与ORM的核心位置如下:

  • Prisma Schema:定义数据模型、索引与关系
  • Prisma Client接入:全局实例化与连接管理
  • 业务模块存储层:对Prisma的封装与事务使用
  • 状态机与迁移脚本:确保历史数据与新字段一致
  • 文档与依赖:数据库结构说明与Prisma版本

    graph TB
    subgraph "数据层"
    PRISMA["Prisma Schema<br/>server/prisma/schema.prisma"]
    CLIENT["Prisma Client<br/>server/src/models/index.ts"]
    end
    subgraph "业务层"
    STORE["存储封装<br/>book-generator.store.ts"]
    STAGE["状态机与并发控制<br/>stage-manager.ts"]
    MIGRATE["迁移脚本<br/>migrate-genstage.ts / sync-genstage.ts"]
    end
    subgraph "文档与依赖"
    DOC["数据库结构文档<br/>docs/database-structure.md"]
    PKG["依赖与版本<br/>server/package.json"]
    end
    PRISMA --> CLIENT
    CLIENT --> STORE
    STORE --> STAGE
    MIGRATE --> PRISMA
    DOC --> PRISMA
    PKG --> PRISMA
    

图表来源

  • schema.prisma
  • index.ts
  • book-generator.store.ts
  • stage-manager.ts
  • migrate-genstage.ts
  • sync-genstage.ts
  • database-structure.md
  • package.json

章节来源

  • schema.prisma
  • index.ts
  • book-generator.store.ts
  • stage-manager.ts
  • migrate-genstage.ts
  • sync-genstage.ts
  • database-structure.md
  • package.json

核心组件

  • Prisma Schema:集中定义实体、字段、索引、唯一约束与关系
  • Prisma Client:全局单例,负责连接与查询
  • 存储封装(BookStore):对Prisma的CRUD封装,包含事务与批量操作
  • 状态机与并发控制:线性阶段模型、乐观锁与资源清理
  • 迁移脚本:历史字段到新字段的迁移与同步

章节来源

  • schema.prisma
  • index.ts
  • book-generator.store.ts
  • stage-manager.ts
  • migrate-genstage.ts
  • sync-genstage.ts

架构概览

数据模型扩展遵循“Schema先行、Client接入、封装调用、状态机保障、迁移兜底”的整体流程。

sequenceDiagram
participant Dev as "开发者"
participant Schema as "Prisma Schema"
participant Client as "Prisma Client"
participant Store as "存储封装(BookStore)"
participant Stage as "状态机(stage-manager)"
participant DB as "MySQL"
Dev->>Schema : 修改/新增模型与索引
Schema->>Client : 生成客户端代码
Client->>DB : 执行迁移/查询
Store->>Client : CRUD/事务
Stage->>Client : 乐观锁状态转移
Client-->>DB : 提交/回滚

图表来源

  • schema.prisma
  • index.ts
  • book-generator.store.ts
  • stage-manager.ts

详细组件分析

Prisma ORM与Schema设计

  • 数据源与生成器:定义provider与数据库连接
  • 实体与字段:使用原生类型注解、默认值、长度限制
  • 关系与外键:@relation声明字段映射与删除策略
  • 索引与唯一:@@index@@unique@@map命名
  • 复合唯一键:如BookChapter的bookId_parentId_level_number

    erDiagram
    USER ||--o{ COMMENT : "评论"
    USER ||--o{ DRAFT : "草稿"
    USER ||--o{ FAVORITE : "收藏"
    USER ||--o{ ORDER : "订单"
    USER ||--o{ PLAY_RECORD : "播放记录"
    USER ||--o{ PLAYLIST : "播放列表"
    USER ||--o{ SIGN_RECORD : "签到"
    USER ||--o{ SUBSCRIPTION : "订阅"
    USER ||--o{ TOKEN_BALANCE : "余额"
    USER ||--o{ TOKEN_USAGE : "用量"
    USER ||--o{ PREFERENCE : "偏好"
    BOOK }o--o{ BOOK_CHAPTER : "章节"
    BOOK ||--o{ VIDEO_PROJECT : "视频项目"
    BOOK }o--o{ FAVORITE : "收藏"
    BOOK_CHAPTER ||--o{ COMMENT : "评论"
    BOOK_CHAPTER ||--o{ PLAY_RECORD : "播放记录"
    BOOK_CHAPTER ||--o{ PLAYLIST_ITEM : "播放列表项"
    BOOK_CHAPTER ||--o{ VIDEO_PROJECT : "视频项目"
    PLAYLIST ||--o{ PLAYLIST_ITEM : "条目"
    PLAYLIST }o--o{ USER : "拥有者"
    ORDER }o--o{ USER : "购买者"
    ORDER }o--o{ SUBSCRIPTION_PLAN : "套餐"
    ORDER ||--o{ TOKEN_USAGE : "用量"
    SUBSCRIPTION }o--o{ USER : "用户"
    SUBSCRIPTION }o--o{ SUBSCRIPTION_PLAN : "套餐"
    

图表来源

  • schema.prisma

章节来源

  • schema.prisma

Prisma Client接入与连接管理

  • 单例初始化:在应用启动时创建PrismaClient
  • 连接生命周期:统一connect与错误处理
  • 导出复用:供各模块导入使用

章节来源

  • index.ts

存储封装(BookStore)与事务

  • 事务边界:发布/取消发布书籍时使用$transaction保证一致性
  • 批量操作:upsert避免重复创建,提升幂等性
  • 查询封装:include关联、orderBy排序、条件筛选
  • 状态映射:outlineJson解析、章节树构建

    sequenceDiagram
    participant Svc as "业务服务"
    participant Store as "BookStore"
    participant Prisma as "Prisma Client"
    participant Tx as "事务"
    participant DB as "MySQL"
    Svc->>Store : publishAlbum(bookId)
    Store->>Tx : 开启事务
    Tx->>Prisma : 更新book.isPublished
    Tx->>Prisma : 更新bookChapter.isPublic(有音频)
    Prisma-->>Tx : 提交
    Tx-->>Store : 成功
    Store-->>Svc : 返回
    

图表来源

  • book-generator.store.ts

章节来源

  • book-generator.store.ts

状态机与并发控制

  • 线性阶段:章节与书籍均采用线性阶段序列,便于顺序推进
  • 转移矩阵:严格限制合法状态转移,防止逆向推进
  • 乐观锁:updateMany带条件校验,失败重试或提示冲突
  • 资源清理:回退时自动清理下游产物(音频/视频URL与时长)

    flowchart TD
    Start(["进入 safeTransition"]) --> CheckAllowed["检查是否允许转移"]
    CheckAllowed --> |否| Error["抛出非法转移错误"]
    CheckAllowed --> |是| CalcClean["计算需要清理的下游资源"]
    CalcClean --> Optimistic["乐观锁写入:updateMany(genStage=当前)"]
    Optimistic --> CountZero{"影响行数=0?"}
    CountZero --> |是| QueryActual["查询实际状态"]
    QueryActual --> SameTarget{"实际状态=目标?"}
    SameTarget --> |是| Skip["跳过已达成"]
    SameTarget --> |否| Conflict["记录冲突并跳过"]
    CountZero --> |否| Done(["完成"])
    

图表来源

  • stage-manager.ts

章节来源

  • stage-manager.ts

历史数据迁移与同步

  • 迁移脚本:将旧字段(status/contentStatus/audioStatus/videoStatus)映射到新字段genStage
  • 同步脚本:结合状态机的安全转移函数,逐条同步并处理并发冲突
  • 推断逻辑:根据子章节状态推断书籍阶段,确保一致性

    sequenceDiagram
    participant Script as "迁移/同步脚本"
    participant Prisma as "Prisma Client"
    participant Stage as "状态机函数"
    participant DB as "MySQL"
    Script->>Prisma : 查询旧字段
    Script->>Script : 推断/计算新genStage
    Script->>Stage : safeTransition/advance/sync
    Stage->>Prisma : 乐观锁更新
    Prisma-->>Stage : 结果
    Stage-->>Script : 成功/跳过
    

图表来源

  • migrate-genstage.ts
  • sync-genstage.ts
  • stage-manager.ts

章节来源

  • migrate-genstage.ts
  • sync-genstage.ts
  • stage-manager.ts

依赖分析

  • Prisma版本:6.x,需与客户端版本匹配
  • 数据库:MySQL,使用Prisma client-js
  • 依赖关系:业务模块通过存储封装间接依赖Prisma Client

    graph LR
    PKG["server/package.json"] --> PRISMA["Prisma 6.x"]
    PKG --> CLIENT["@prisma/client"]
    STORE["book-generator.store.ts"] --> CLIENT
    STAGE["stage-manager.ts"] --> CLIENT
    SCHEMA["schema.prisma"] --> PRISMA
    

图表来源

  • package.json
  • schema.prisma
  • book-generator.store.ts
  • stage-manager.ts

章节来源

  • package.json
  • schema.prisma
  • book-generator.store.ts
  • stage-manager.ts

性能考虑

  • 索引设计
    • 优先覆盖高频查询条件,如用户维度、状态、时间范围
    • 复合索引避免回表,如Book(userId,status)、BookChapter(bookId,parent,level,number)
  • 查询优化
    • 使用select精确投影,减少字段传输
    • 使用orderBy与limit控制结果集大小
    • 避免N+1查询,合理使用include与嵌套where
  • 写入优化
    • 批量upsert替代多次insert/update
    • 事务合并多个写操作,减少往返
  • 状态机与幂等
    • 乐观锁降低锁竞争,提升并发吞吐
    • 资源清理避免脏数据残留

[本节为通用指导,无需具体文件分析]

故障排查指南

  • 连接失败
    • 检查DATABASE_URL环境变量与数据库可达性
    • 确认Prisma Client初始化与connect调用
  • 迁移异常
    • 查看迁移日志与lock文件,必要时手动清理lock
    • 使用迁移脚本或同步脚本修复genStage不一致
  • 并发冲突
    • safeTransition返回0影响行数时,检查实际状态与转移矩阵
    • 避免跨模块同时修改同一记录,必要时加分布式锁
  • 查询慢
    • 为where/orderBy列建立复合索引
    • 使用EXPLAIN分析执行计划,调整索引与查询条件

章节来源

  • index.ts
  • migrate-genstage.ts
  • sync-genstage.ts
  • stage-manager.ts

结论

通过“Schema先行、Client接入、封装调用、状态机保障、迁移兜底”的整体设计,平台实现了可演进、可扩展、可维护的数据模型。遵循本文的扩展流程与最佳实践,可在保证向后兼容与数据一致性的前提下,安全地引入新表、字段与索引,持续提升系统性能与稳定性。

[本节为总结,无需具体文件分析]

附录

数据模型扩展实践清单

  • 在schema.prisma中新增/修改模型与字段,补充索引与唯一约束
  • 生成客户端代码并进行本地测试
  • 在存储封装中添加/调整CRUD方法,必要时开启事务
  • 编写迁移脚本或同步脚本,处理历史数据映射
  • 在状态机中补充/校验状态转移矩阵,确保并发安全
  • 编写单元/集成测试,覆盖关键路径与边界条件
  • 评估并添加必要的索引,优化查询性能
  • 更新文档与API契约,保持内外一致

章节来源

  • schema.prisma
  • book-generator.store.ts
  • stage-manager.ts
  • migrate-genstage.ts
  • sync-genstage.ts