# Flyway 全面引入 — 治本地/测试/正式表结构不一致根因 **日期**: 2026-05-05 **类型**: chore(基础设施引入,零业务影响) **Release PR**: wx/HL #1686(dev → 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.xml` 加 `flyway-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 显式 `8.5.13`。 ### 坑 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」一气呵成,**根因彻底治理**。