144 lines
7.4 KiB
Markdown
144 lines
7.4 KiB
Markdown
# 开发数据库 Schema 基线与版本门禁设计规格
|
|
|
|
- 功能编号:GOV-007
|
|
- 规格版本:0.1
|
|
- 状态:approved_for_review
|
|
- 日期:2026-08-13
|
|
|
|
## 背景与目标
|
|
|
|
数据库正式启用后,每个新应用版本开始开发前都需要一份可审计的结构起点。只保存迁移脚本不能证明开发数据库在版本开始时的真实结构,也无法发现手工改表造成的漂移。
|
|
|
|
本功能建立强制门禁:开始开发下一个语义化版本前,从开发环境数据库导出当前已发布版本的完整 Schema,规范化、校验并纳入 Git。开发流程和脚本禁止连接、读取或探测生产数据库。
|
|
|
|
## 版本与命名
|
|
|
|
基线按“被备份的当前已发布版本”命名,而不是即将开发的版本。例如开始开发 `v0.0.6` 前,封存 `v0.0.5` 状态:
|
|
|
|
```text
|
|
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。
|