Files

7.4 KiB

开发数据库 Schema 基线与版本门禁设计规格

  • 功能编号:GOV-007
  • 规格版本:0.1
  • 状态:approved_for_review
  • 日期:2026-08-13

背景与目标

数据库正式启用后,每个新应用版本开始开发前都需要一份可审计的结构起点。只保存迁移脚本不能证明开发数据库在版本开始时的真实结构,也无法发现手工改表造成的漂移。

本功能建立强制门禁:开始开发下一个语义化版本前,从开发环境数据库导出当前已发布版本的完整 Schema,规范化、校验并纳入 Git。开发流程和脚本禁止连接、读取或探测生产数据库。

版本与命名

基线按“被备份的当前已发布版本”命名,而不是即将开发的版本。例如开始开发 v0.0.6 前,封存 v0.0.5 状态:

database/schema-baselines/v0.0.5/
├── schema.sql
├── manifest.yaml
└── checksum.sha256

每个应用版本开始前都生成一次。即使 Schema 未变化,也生成新版本目录,以相同内容校验值证明没有结构漂移。

唯一允许的数据来源

  • 只允许读取开发环境数据库。
  • 加载开发专用本地配置,要求 APP_ENV=development。
  • 数据库名固定为 a_share_analysis_dev;名称不匹配立即终止。
  • 启用真实导出时主机必须为 127.0.0.1、localhost 或 ::1;远程开发库必须先通过运维建立本地 SSH 隧道,脚本不接受任意远程目标。
  • 禁止通过命令参数覆盖环境类型、数据库名或传入任意 env 文件路径。
  • 禁止连接、读取、探测或导出生产数据库;生产备份属于独立运维流程,不进入开发门禁。
  • 推荐使用只拥有开发库结构读取和例程查看权限的专用账号,不授予生产访问能力。

即使主机名看似本地,脚本也必须验证环境和数据库名;不能只依赖地址白名单判断安全。

导出范围

使用 MySQL 5.7 客户端 mysqldump,仅导出结构,不包含任何表数据。基线必须完整包含:

  • 数据库表、列、主键、索引、外键与表选项。
  • 视图。
  • 触发器。
  • 存储过程和函数。
  • Event Scheduler 事件。

导出命令必须使用 --no-data --routines --triggers --events,并使用符合 MySQL 5.7 的选项。执行元数据查询的 mysql 客户端和执行导出的 mysqldump 客户端必须分别验证为 5.7.x。账号凭据通过开发 env 或受控客户端配置提供,禁止出现在命令参数、日志或清单中。

规范化

原始 mysqldump 输出经过确定性规范化后才能进入 Git:

  • 删除导出时间、完成时间、客户端路径等不稳定注释。
  • 删除或规范化环境绑定的 DEFINER,避免恢复时绑定个人账号。
  • 删除由数据增长产生的 AUTO_INCREMENT=<当前值>,保留列的自增属性。
  • 统一换行符与文件末尾换行。
  • 禁止把主机、端口、账号、密码或客户端配置路径写入 SQL。
  • 不改变表、视图、触发器、例程和事件的业务定义。

规范化工具必须通过固定输入/输出测试证明不会误删业务 SQL。

校验与清单

manifest.yaml 至少记录:

  • application_version:被备份的已发布版本。
  • git_commit:该版本标签最终指向的提交。
  • source_environment: development。
  • database_name: a_share_analysis_dev。
  • MySQL 客户端和服务端精确版本。
  • charset: utf8mb4。
  • collation: utf8mb4_general_ci。
  • 生成时间与生成工具版本。
  • 是否包含表、视图、触发器、例程和事件。
  • 规范化 SQL 的 SHA-256。

checksum.sha256 使用标准格式记录 schema.sql 校验值。流程必须重新计算并验证清单、校验文件和实际 SQL 三者一致。

强制阻断条件

出现以下任一情况,不允许进入下一版本开发:

  • 当前已发布版本没有 Schema 基线,且数据库已启用。
  • APP_ENV 不是 development。
  • 数据库名不是 a_share_analysis_dev。
  • 检测到生产配置文件、生产环境标识或禁止的连接目标。
  • MySQL 客户端或服务端不是 5.7.x。
  • 字符集或排序规则不是 utf8mb4 / utf8mb4_general_ci。
  • 导出缺少视图、触发器、存储过程/函数或事件的范围声明。
  • SQL 包含 DEFINER、不稳定导出注释、当前 AUTO_INCREMENT 值或疑似凭据。
  • 校验值不一致、目标版本目录已存在且内容不同,或 Git 工作区存在无法解释的 Schema 改动。

禁止覆盖既有版本基线。需要修正时新增带原因的治理记录和修复提交,不静默重写已发布事实。schema:verify 是本地内容校验;governance:start 还要求基线文件已被 Git 跟踪、工作区无改动、当前分支已推送以及远程发布标签仍指向清单提交。

首次启用与未启用状态

当前 MySQL 尚未启用,因此在开发新版本前允许记录结构备份“不适用”,但必须能证明功能开关为关闭,且不得创建伪造的空 schema.sql 冒充数据库基线。

首次启用 MySQL 的版本必须:

  1. 通过迁移创建开发库初始结构。
  2. 在 MySQL 5.7 开发环境验证字符集与排序规则。
  3. 发布时建立首份真实 Schema 基线。
  4. 后续每个版本开始前严格执行本门禁。

开发流程位置

下一版本开发前顺序为:

  1. 确认当前已发布版本和标签提交。
  2. 判断 MySQL 功能开关;未启用则保存可验证的不适用记录。
  3. 已启用时从开发数据库导出、规范化并校验完整 Schema。
  4. 将当前发布版本基线作为独立中文提交推送 Gitea。
  5. 确认工作区干净和远程同步成功。
  6. 再创建下一版本 PRD、设计与功能档案,执行 GitNexus 开发前分析。

数据库迁移必须从上一基线在 MySQL 5.7 开发环境正向执行验证。禁止直接修改共享开发表代替迁移脚本。

安全边界

  • Schema 基线只含结构,不含业务数据、账号数据或生产数据。
  • 导出脚本不得回显秘密,也不得接受密码命令行参数。
  • 开发工具和代理无权使用生产 env 或生产数据库验证功能。
  • 基线提交前扫描疑似凭据、生产主机、DEFINER 和数据 INSERT。
  • Schema 基线进入 Git 后视为公开给仓库使用者,任何敏感对象名称或注释都应在数据库设计阶段避免。

实施范围

GOV-007 将实现数据库目录规范、开发 env 模板扩展、确定性 SQL 规范化工具、导出/校验脚本、自动化测试、开发流程门禁和完整追溯档案。由于当前 MySQL 未启用,本功能只验证阻断逻辑、规范化固定样本和“不适用”路径,不连接任何数据库。

验收标准

  • 开发流程明确每个应用版本开始前建立上一已发布版本的开发库 Schema 基线。
  • 脚本只接受 development 和固定开发库名,无法通过普通参数切换到生产配置。
  • 导出范围包含表、视图、触发器、存储过程/函数和事件且不含数据。
  • 规范化稳定移除时间注释、DEFINER 和当前 AUTO_INCREMENT 值,但保留业务 SQL。
  • 清单和 SHA-256 格式可自动校验。
  • MySQL 5.7、utf8mb4、utf8mb4_general_ci 不符合时阻断。
  • 当前未启用 MySQL 时使用可验证“不适用”记录,不伪造空 Schema。
  • 自动化测试、治理门禁、GitNexus 和双 Review 通过。
  • 中文提交和对应版本标签精确推送 Gitea。