1. Flyway 概述:Flyway 是什么、核心价值、版本迁移的基本概念与工作流程
1.1 什么是 Flyway
Flyway 是一款开源的数据库版本控制工具,采用 “约定优于配置” 的设计哲学,通过版本化的 SQL 脚本或 Java 迁移类,对数据库 Schema 进行可重复、可追溯的变更管理。它本质上是一个 数据库 Schema 的 Git,让每一次 DDL/DML 变更都像代码提交一样被记录、校验和回放。
核心定位:Flyway 不是 ORM 框架的附属品,而是一个独立于应用框架的数据库 CI/CD 组件,支持 Spring Boot、Quarkus、Micronaut 以及纯 Java/命令行环境。
| 维度 | 说明 |
|---|---|
| 工具类型 | 数据库 Schema 版本管理工具(Database Migration Tool) |
| 输入形式 | SQL 脚本(.sql)或 Java 迁移类(Java-based Migration) |
| 状态追踪 | 在目标数据库中自动创建 flyway_schema_history 元数据表 |
| 运行模式 | 命令行、Java API、Maven/Gradle 插件、Spring Boot 自动配置 |
| 支持数据库 | MySQL、PostgreSQL、Oracle、SQL Server、MariaDB、H2 等 20+ 种 |
1.2 核心价值
- 可重复性:开发、测试、生产环境执行同一套迁移脚本,消除“在我机器上能跑”的 Schema 差异。
- 可追溯性:每次迁移的校验和(Checksum)、执行时间、执行人、脚本内容全部记录在
flyway_schema_history表中,形成完整的审计链路。 - 幂等性:通过版本号唯一性保证同一脚本不会重复执行;失败时支持清理(Clean)和修复(Repair)操作。
- CI/CD 集成:可嵌入构建流水线,在应用部署前自动完成 Schema 升级,避免人工漏跑或错跑脚本。
- 团队协作:多人并行开发时,通过版本号冲突检测和基线(Baseline)机制,减少 Schema 合并冲突。
实践建议:在微服务架构中,每个服务独立维护自己的 Flyway 迁移目录,避免跨服务的 Schema 耦合。Flyway 只管理本服务对应的数据库 Schema,不处理跨库分布式事务。
1.3 版本迁移的基本概念
| 概念 | 说明 |
|---|---|
| 迁移(Migration) | 一次 Schema 变更的单元,可以是 SQL 脚本或 Java 类 |
| 版本号(Version) | 迁移的唯一标识,格式如 1.0、2.1.3,决定执行顺序 |
| 描述(Description) | 迁移的简短说明,如 create_user_table,用于日志和元数据 |
| 校验和(Checksum) | 迁移内容的 SHA-256 哈希值,用于检测脚本是否被篡改 |
| 基线(Baseline) | 对已有数据库打上版本标记,使 Flyway 从该版本开始管理后续迁移 |
| 撤销(Undo) | 回滚指定版本的迁移(企业版功能,社区版不支持) |
| 重复迁移(Repeatable Migration) | 每次校验和变化时重新执行的迁移,适用于视图、函数、存储过程 |
迁移文件命名规范:
前缀 + 版本号 + 分隔符 + 描述 + 后缀
示例:
V1__create_user_table.sql
V2_1__add_email_column.sql
V3__insert_initial_data.sql
R__my_view.sql (重复迁移,无版本号)
U1__undo_create_user_table.sql (撤销迁移,企业版)
避坑提示:版本号不要使用纯数字如
V1、V2,建议使用语义化版本如 V1.0、V1.1,避免在版本回退或补丁时出现排序歧义。Flyway 按版本号字符串的自然排序执行,V10 会在 V9 之后执行,但 V1.10 会在 V1.9 之后执行。
1.4 工作流程
Flyway 的迁移执行遵循 “检查 → 校验 → 执行 → 记录” 的闭环流程,具体步骤如下:
- 扫描:Flyway 扫描配置的迁移路径(默认
classpath:db/migration),解析所有迁移文件的版本号和校验和。 - 校验:读取目标数据库的
flyway_schema_history表,对比已执行迁移的校验和是否与本地文件一致。不一致则抛出异常,阻止迁移。 - 排序:按版本号升序排列未执行的迁移,确定执行顺序。
- 锁定:在集群或多实例部署场景下,通过数据库锁(或表锁)确保同一时刻只有一个实例执行迁移,避免并发冲突。
- 执行:依次执行每个迁移脚本。SQL 迁移在事务内执行(如果数据库支持 DDL 事务);Java 迁移由开发者控制事务边界。
- 记录:每个迁移执行成功后,在
flyway_schema_history表中插入一条记录,包含版本号、描述、校验和、执行时间、脚本内容(可选)。 - 完成:所有待执行迁移执行完毕后,释放锁,返回迁移结果。
1.5 迁移类型对比
| 类型 | 命名模式 | 执行时机 | 典型用途 |
|---|---|---|---|
| 版本化迁移(Versioned) | V{version}__{description}.sql |
每个版本仅执行一次 | 建表、加字段、加索引、数据迁移 |
| 重复迁移(Repeatable) | R__{description}.sql |
每次校验和变化时执行 | 视图、函数、存储过程、物化视图 |
| 撤销迁移(Undo) | U{version}__{description}.sql |
手动触发撤销指定版本 | 回滚 DDL 变更(企业版) |
| Java 迁移 | 实现 JavaMigration 接口 |
按版本号顺序执行 | 复杂数据转换、调用外部 API、条件迁移 |
最佳实践:生产环境中优先使用版本化 SQL 迁移,保持迁移脚本的声明式和可读性。仅在需要复杂业务逻辑(如数据清洗、调用第三方服务)时才使用 Java 迁移。重复迁移适合管理视图和函数,避免每次修改都生成新的版本号。
1.6 元数据表结构
flyway_schema_history 表是 Flyway 的“大脑”,记录了所有迁移的执行历史。其核心字段如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
installed_rank |
INT | 执行顺序序号 |
version |
VARCHAR | 迁移版本号(可空,重复迁移为空) |
description |
VARCHAR | 迁移描述 |
type |
VARCHAR | 迁移类型:SQL、JDBC、SPRING_JDBC |
script |
VARCHAR | 迁移脚本名称 |
checksum |
INT | 脚本内容的校验和 |
installed_by |
VARCHAR | 执行迁移的数据库用户 |
installed_on |
TIMESTAMP | 执行时间 |
execution_time |
INT | 执行耗时(毫秒) |
success |
BOOLEAN | 是否执行成功 |
关键提醒:永远不要手动修改
flyway_schema_history 表。如果迁移失败需要修复,应使用 Flyway 的 repair 命令清除失败的记录,而不是直接 DELETE 或 UPDATE。手动篡改元数据会导致校验和不一致,引发后续迁移异常。