Files
baiyue-firstleg/deploy/sql/数据库迁移操作手册.md
2026-09-23 17:47:50 +08:00

10 KiB
Raw Permalink Blame History

数据库迁移操作手册

本文是开发、测试和发布人员的日常操作入口。设计原则和生产边界见仓库文档 数据库版本迁移与 Jenkins 自动发布方案;当前阶段的初始化事实见本目录 README.md。

先分清两类 SQL

类型 位置 用途 能否在已有业务库重复执行
空库初始化 deploy/sql/头程数据库统一增量-MySQL8.sql、海外区域统一增量-MySQL8.sql 初始化一个不存在或获授权清空的区域数据库 不能
版本迁移 `deploy/sql/migrations/{cn overseas}//V<数字>__<说明>.sql` 机制启用后对已有数据库逐步升级

当前测试分支只完成了版本迁移的离线工具和目录骨架。没有冻结基线、没有具体业务变更时,不要复制初始化 SQL 生成 V1,也不要连接测试或生产数据库试跑。

编号与功能分支规则(2026-09-22 确认)

SQL 编号统一保持 V1、V2、V3、V4、V5……,不使用时间戳。每个数据库独立计数,由工具生成下一个整数;数字变长不需要重置或重新编号。

  • 有数据库逻辑变更才新增迁移;普通提交、重复测试和重复部署不增加 SQL 编号。
  • 同一未冻结、未在保留历史环境执行的变更可以反复编辑;成功执行后不改内容、不改编号,修复新增迁移。失败候选的受控修订仍按方案第 13.2.1 节处理。
  • 功能分支从最新 main 创建;进入共享测试前先拉取并合并最新 main,解决代码和同库编号冲突。只允许调整尚未冻结、未在保留历史环境执行的草稿。
  • 两人并行开发,共享测试、合并和发布依次进行。前一功能完成发布或处理失败后,下一功能同步 main 再进入测试;若前一功能留下未合并 SQL 或未决失败,先处理测试起点,不能直接继续验收。
  • 测试后 main 又变化,必须重新同步和验证。合并 main 后构建正式候选并再次自动验证,生产使用这份正式候选,不重新构建或修改 SQL。

生产发布版本另外记为 release-1、release-2……,不与 SQL 编号绑定。 例如 release-12 中 Auth 是 V3、Order 是 V7;只有代码变化也可以发布 release-13,SQL 编号保持不变。

目标流程由 Jenkins 为新的生产候选自动分配发布编号;成功后更新当前生产版本并记录 Git 标签、完整提交、镜像 digest 和 SQL 清单。失败编号保留且不复用,同一制品重试沿用原编号;修改制品后分配新编号并重新验证。main 是已合并代码,生产实际版本以成功发布记录为准;发布失败时还需核对各库、各服务的实际状态,不能假定全部未变。

当前工具只依据当前分支的迁移目录生成整数编号;跨分支冲突预检、main 同步门禁、release-N 分配和标签归档尚待接入,不因写入本手册就视为已自动执行。

日常开发:新建和修改迁移

以下命令均从 baiyue-firstleg 根目录执行,PowerShell 和 Bash 都可以使用 Node 命令。

1. 确认所属区域和 schema

打开 migration-scopes.json,只选择已登记的区域和 schema。服务没有数据库时不创建空迁移;例如 gateway 不对应 schema。

node deploy/sql/scripts/db-migrations.mjs check

2. 自动创建迁移文件

node deploy/sql/scripts/db-migrations.mjs new `
  --region CN `
  --schema baiyue_auth `
  --description add_login_audit

工具会读取该 schema 当前最大编号并创建下一个文件,例如:

deploy/sql/migrations/cn/baiyue_auth/V1__add_login_audit.sql

开发者只输入区域、schema 和说明,不输入版本号。说明中的英文字母、数字和下划线会用于文件名;只有中文说明时文件名使用 change,完整中文说明仍保留在 SQL 头部。并发创建使用独占文件创建,不覆盖已有文件。

3. 填写 SQL 和断言

在生成的文件中完成实际 SQL,并补充文件头的前置、后置检查。一个文件只修改一个 schema,不写 USE、CREATE DATABASE、跨 schema 限定名或真实业务数据。

同一文件在开发阶段可以反复编辑,但一旦在保留历史的环境成功执行或进入冻结候选,就不能再改。没有成功记录但测试候选已失败时,只有方案第 13.2.1 节的受控修订流程可以保留原编号修正。

4. 提交前离线检查

node deploy/sql/scripts/db-migrations.mjs check
node --test deploy/sql/scripts/db-migrations.test.mjs scripts/script-documentation-contract.test.mjs

check 会验证范围映射、文件名、重复版本、跨 schema 引用、跨库控制语句,以及可选的受保护文件清单。它不连接数据库,也不证明 SQL 语义正确。

生成测试候选

1. 只选择本次要发布的服务

node deploy/sql/scripts/db-migrations.mjs plan `
  --services auth,iam `
  --regions CN `
  --out .codex-tmp-release-manifest.json

plan 自动生成逐库目标、完整迁移文件列表和 SHA-256。它只包含选中服务及评审确认的 schema;同一提交中其他服务的 SQL 不会被自动带入。没有迁移文件的允许 schema 目标为 0.0.0,范围外 schema 不生成目标。

生成的 manifest 是制品,不是开发者长期维护的源码文件。不要手改、提交或在测试与生产之间重新生成;测试通过后应复用同一个 manifest、SQL 包和镜像 digest。

2. 查看只读执行计划

node deploy/sql/scripts/db-migrations.mjs run `
  --manifest .codex-tmp-release-manifest.json `
  --dry-run

当前阶段 run 只支持 --dry-run,用于确认要执行哪些库和版本。真实 Flyway 执行、测试数据库凭据、环境锁和 Jenkins 阶段属于后续阶段 C,尚未由本命令启用。不要自行设置开关连接真实数据库。

测试环境的目标流程

完成基线登记和阶段 C 接入后,测试部署按以下顺序自动完成:

  1. 构建并冻结代码、SQL manifest 和全部目标镜像。
  2. 获取测试环境锁,核验实例身份、基线和当前 Flyway 历史。
  3. 对允许迁移的 schema 做全量预检;任何库失败都不开始其他库的写入。
  4. Flyway 按完整版本链执行待迁移版本,成功版本自动跳过。
  5. 严格复验历史、结构和必要种子。
  6. 只有数据库阶段全部通过,才部署同一批应用镜像。
  7. 同一候选重复执行时只执行数据库尚未成功的版本,不重复执行成功 SQL。

测试环境验证至少包括空库到目标、上一发布版本到目标、带合成数据升级、重复部署、失败阻断应用部署和跨区域部分成功。测试报告必须绑定 manifest、SQL 哈希、镜像 digest 和测试起点。

生产晋级

生产不重新生成 SQL,也不重新编号。只选择已经通过测试的原候选制品,执行器只处理生产当前缺少的成功迁移;已成功的版本自动跳过。生产数据库高于候选目标、存在未纳入清单的成功迁移、失败记录、校验和变化或起点与测试演练不一致时,发布直接阻断。

生产迁移成功后才部署同批镜像。应用回滚不执行旧 SQL;只有经过兼容性记录证明的旧镜像才允许回滚。数据库逆向回滚依赖受控备份恢复或新的向前修复迁移。

失败时怎么处理

情况 处理方式
check 失败 修正范围、文件名或 SQL 引用后重新检查;不能用忽略参数跳过
测试迁移失败、从未成功且未进生产 按方案 13.2.1 撤销旧候选、确认无残留和排队任务后,允许修订同一编号;旧制品只读保留,新候选重新完成空库、升级和数据测试
任一环境已成功执行该版本 不修改原文件、不复用编号修订;创建新的向前修复迁移
生产迁移失败或部分 DDL 已提交 停止应用部署,保留失败历史和证据,进入专项恢复;不能简单加版本号掩盖状态
国内成功、海外失败 保留国内成功结果,停止整批应用部署,先按区域恢复或补齐证据;不重放国内成功版本
Jenkins 超时、取消或重启 先确认数据库会话和真实历史,状态未确认前禁止重试或清理制品

日常维护规则

代码和目录

  • migration-scopes.json 是区域、schema、服务归属和顺序的低频配置;增加服务、改数据库归属或调整依赖时才修改,并由两名开发者一起评审。
  • migrations/ 是上线迁移唯一事实来源;不要把模块 resources/db/、历史脚本或临时 SQL 当作发布目录。
  • 版本号只在同一 schema 内递增,废弃编号不重新分配给其他业务目的;不同 schema 可以使用相同编号。
  • 成功迁移、冻结候选、发布 manifest、失败原文和修订记录都必须长期留档;普通构建清理不能删除它们。
  • 不提交生成的 manifest、日志、凭据、连接串或真实数据;Jenkins 制品保存 SQL、manifest 和镜像 digest。

什么时候需要新增迁移

新增或修改表、列、索引、约束、默认值、触发器、必要系统种子,以及会改变数据库读写要求的 Mapper/持久化 SQL,都要在评审中确认是否需要迁移。需要时用 new 创建;不需要时记录具体理由并补受影响数据库读写测试,不能只因为没有 SQL 文件就默认通过。

谁负责什么

变更开发者负责 SQL 语义、前后断言、数据影响和代码关联;另一名开发者检查范围、兼容性和测试证据;发布执行人只选择已通过测试的候选并触发自动流程。任何人都不应直接登录服务器手工执行生产 SQL。

当前实现边界

当前测试分支已经可以使用 new、check、plan 和 run --dry-run,并有对应离线合同测试。以下事项仍未启用:

  • 生产或测试数据库基线登记;
  • Flyway 实际执行和历史表校验;
  • Jenkins 的数据库阶段、环境锁和构建/部署解耦;
  • 功能分支同步检查、合并后候选验证、生产 release-N 自动编号及发布标签归档;
  • 真实测试环境部署与生产晋级。

因此现在可以开始编写和评审迁移文件,但不能把离线检查通过当作测试或生产发布通过。