hl-api-changelog/changelogs/2026-05/05_chore_flyway_full_introduction.md
API Changelog Bot cc29f8ef91 docs(2026-05-07): refund 申诉补企微 OA 提交 (PR #1774)
后端纯内部修复,前端无配合,运维补 nacos 三套 + 7 控件 ID。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:27:01 +08:00

4.6 KiB

Flyway 全面引入 — 治本地/测试/正式表结构不一致根因

日期: 2026-05-05 类型: chore基础设施引入,零业务影响 Release PR: wx/HL #1686dev → main 已合并) 关联 PRs: #1681 (oneshot SQL 补漏) / #1682 (pilot) / #1683 (flyway-mysql artifact 修) / #1684 (阶段 2 批量铺) / #1685 (dep 移 hl-starter-mybatis 修) 关联工单: #1678

背景

2026-05-05 一晚连续 3 次 V*.sql 测试服漏跑(PR #1659/#1661/#1668 → BadSqlGrammar 全军),根因项目无 Flyway,DB migration 全靠运维手工跑。Flyway 是 Java 生态最常用的 DB schema 版本管理,核心机制:

  • 应用启动时自动建 flyway_schema_history 表,记录哪些 V*.sql 已跑
  • db/migration/ 找未跑的 V*.sql → 顺序自动 apply
  • 多环境(本地/测试/正式)启动一致 → 表结构永远同步

改动范围

Flyway dep 集中管理

hl-common/hl-starter-mybatis/pom.xmlflyway-core (Spring Boot 2.7.18 BOM 管 8.5.13) + flyway-mysql:8.5.13 (BOM 不管,显式 version)。4 个 DB service (user/order-v2/product-v2/resource) 全继承(3 service 直接依赖 starter,resource-service 通过 hl-common-mybatis 间接;dep 放 starter 是因为 order-v2 不依赖 hl-common-mybatis,放后者拿不到)。

4 个 DB service application.yml 配 Flyway

Service DB schema baseline-version
hl-user-service hl_user_service 20260505.009
hl-order-service-v2 hl_order_service_v2 20260505.010
hl-product-service-v2 hl_product_service 20260418
hl-resource-service hl_resource_service 0 (无历史 V*.sql)

baseline-on-migrate=true + validate-on-migrate=true + placeholder-replacement=false

不需 Flyway 的 service

  • hl-mp-service: 无 DB(application.yml 显式 exclude DataSourceAutoConfiguration)
  • hl-gateway: 无 DB

测试服验证全绿

user-service: history 1 行 baseline 20260505.009 / Flyway 8.5.13 / validated 7 / up to date
order-v2:     history 1 行 baseline 20260505.010 / validated 3 / up to date
product-v2:   history 1 行 baseline 20260418 / validated 1 / up to date
resource-service: history 2 行 (BASELINE 0 + V99999999.001 pilot) / validated 2 / up to date

正式环境验证全绿

dev → main release PR #1686 (24e87f6f) 合并后,prod 4 service 串行 K8s rolling deploy 全部 success,8 pod 全 1/1 ready。

prod /admin/wx-security/hit-log/page         → code:200 records:[] total:0
prod /admin/wx-security/blacklist/page       → code:200
prod /admin/wx-security/whitelist/page       → code:200
prod /admin/wx-security/manual-review/page   → code:200
prod /admin/wx-security/user-risk/list       → code:200 返 2 条预置规则
prod /admin/user/avatar-rejected/page        → code:200
prod /mp/review/featured                     → code:200

Schema 0 改动,业务全绿,Flyway 在 prod 4 schema 自动 baseline 写入元数据(只写 1 行 history,不跑任何 DDL)。

期间踩 2 个坑

坑 1: Flyway 8.x MySQL 支持拆 flyway-mysql artifact

PR #1682 pilot 启动炸 Unsupported Database: MySQL 8.0。Spring Boot 2.7.18 BOM 管 flyway-core 8.5.13,但不管 flyway-mysql。Flyway 9.x 才把 flyway-mysql 加进 Spring Boot BOM。修复 PR #1683 显式 <version>8.5.13</version>

坑 2: dep 必须放 hl-starter-mybatis 不能放 hl-common-mybatis

PR #1684 把 Flyway dep 加 hl-common-mybatis,但 hl-order-service-v2 只依赖 hl-starter-mybatis(没依赖 hl-common-mybatis),导致 order-v2 部署后 Spring Boot autoconfig 缺 flyway-core jar silently skip,Flyway 没启动。修复 PR #1685 dep 移到 hl-starter-mybatis(跟 mybatis-plus 同 starter 集中管理)。

后续团队铁律(已落 memory)

  1. V.sql 合 dev 后冻结* — Flyway 严格校验 checksum,合并后改 1 个字符启动炸。要修发新 V*.sql,旧文件保留。
  2. 新增 DDL 的 PR body 必列「本 PR 是否含 V.sql 变更」*,虽然 Flyway 自动 apply,显式列出便于 review。
  3. 跨 schema 反模式禁止: 一个 V*.sql 只 ALTER 本 service schema 的表(详见 cross-db-migration-module-misplaced-causes-skip.md)。

通知

  • @mmg: 后端 schema 变更工作流升级,以后无须等运维手动跑 SQL,部署即生效
  • 旧 memory P0 铁律「项目无 Flyway, V*.sql 必须手工跑」已删除
  • 新 memory P0 铁律「V*.sql 合 dev 后冻结(Flyway checksum 严格)」已落地

历史价值

Flyway 引入是今晚一连串 BUG 反思后的根因治理。从「网关路由 404」(PR #1679) → 「SQL 漏跑 BadSqlGrammar」(PR #1681) → 「Flyway 全面引入」(PR #1682-#1685) → 「prod 自动 baseline」一气呵成,根因彻底治理