Flyway 工作原理:迁移机制、版本号解析、校验与修复、基线版本
Flyway 的核心设计理念是“约定优于配置”,通过一套标准化的迁移文件命名规则和版本号解析逻辑,自动管理数据库模式的演进。理解其底层工作原理,是构建可靠数据库迁移架构的前提。
2.1 迁移机制:状态机与元数据表
Flyway 在目标数据库中维护一张名为 flyway_schema_history 的元数据表(默认名称,可配置),用于记录所有已执行的迁移记录。每次执行迁移时,Flyway 会执行以下状态机流程:
- 扫描:读取文件系统或类路径下的所有迁移脚本。
- 比对:将扫描到的脚本版本号与
flyway_schema_history表中的已执行记录进行比对。 - 校验:对已执行过的脚本进行 checksum 校验,确保未被篡改。
- 执行:按版本号升序执行所有未应用的迁移脚本。
- 记录:将每次成功执行的迁移信息写入元数据表。
关键元数据字段:
installed_rank:执行顺序号version:迁移版本号description:迁移描述type:迁移类型(SQL/JDBC/SPRING)checksum:脚本内容的 CRC32 校验值installed_on:执行时间戳success:执行状态(1 成功 / 0 失败)
2.2 版本号解析:命名规范与排序规则
Flyway 通过文件命名来识别迁移脚本的版本号和类型。标准命名格式如下:
前缀 + 版本号 + 分隔符 + 描述 + 后缀
示例:
V1__create_user_table.sql
V2.1__add_email_column.sql
V3.0.1__insert_initial_data.sql
R__daily_cleanup_view.sql (可重复迁移,无版本号)
| 组成部分 | 说明 | 示例 |
|---|---|---|
| 前缀 | V 表示版本化迁移,R 表示可重复迁移,U 表示撤销迁移(社区版不支持) |
V / R |
| 版本号 | 数字与点号组合,支持语义化版本(如 1.2.3) | 1 / 2.1 / 3.0.1 |
| 分隔符 | 双下划线 __ 将版本号与描述隔开 |
__ |
| 描述 | 下划线分隔的单词,最终会写入元数据表 | create_user_table |
| 后缀 | .sql 或 .java 等 |
.sql |
版本号排序规则: Flyway 将版本号按点号分割为整数数组,从左到右逐段比较。例如:
1.9 < 1.10 < 2.0。注意 1.10 大于 1.9,这是与纯字符串排序的关键区别。
2.3 校验与修复:Checksum 机制与修复策略
Flyway 在每次执行 migrate 或 validate 命令时,会对所有已执行过的迁移脚本重新计算 CRC32 checksum,并与元数据表中存储的原始值进行比对。如果发现不一致,Flyway 会抛出校验失败异常并阻止迁移继续执行。
常见校验失败场景:
- 开发人员修改了已提交到版本控制并已执行过的迁移脚本。
- 不同环境间迁移脚本内容不一致(如开发环境与生产环境脚本不同步)。
- 文件编码或换行符在不同操作系统间被自动转换。
修复策略:
- 手动修复:在元数据表中删除或修改对应记录(仅限紧急情况,不推荐)。
- Flyway repair 命令:自动清除失败的迁移记录,并将已执行脚本的 checksum 重新对齐到当前文件内容。
- 最佳实践:永远不要修改已执行过的迁移脚本;如需变更,应创建新的迁移版本。
# 修复命令示例
flyway repair
# 修复操作包括:
# 1. 删除所有失败的迁移记录(success=0)
# 2. 重新对齐已成功迁移的 checksum 值
# 3. 移除已删除迁移脚本对应的历史记录
2.4 基线版本:从非空数据库开始
当 Flyway 首次应用于一个已有表结构的数据库时,需要设置基线版本(Baseline)。基线版本告诉 Flyway:“这个数据库已经处于某个版本状态,不要尝试执行比这个版本更早的迁移脚本。”
基线版本的工作流程:
- 执行
flyway baseline命令,指定基线版本号(如 1.0)。 - Flyway 在元数据表中插入一条基线记录,标记当前数据库状态。
- 后续执行
flyway migrate时,只会执行版本号大于基线版本的迁移脚本。
基线版本最佳实践:
- 基线版本号应等于或略低于当前数据库的实际版本状态。
- 基线后立即执行一次
flyway migrate验证基线设置是否正确。 - 对于全新数据库,无需设置基线,Flyway 会自动从第一个迁移脚本开始执行。
- 基线版本一旦设置,不建议修改;如需调整,应使用
flyway repair重新对齐。
2.5 迁移类型对比总结
| 迁移类型 | 前缀 | 版本号 | 执行时机 | 典型用途 |
|---|---|---|---|---|
| 版本化迁移 | V |
有(如 1.0、2.1) | 每个版本仅执行一次 | 表结构变更、索引创建、数据迁移 |
| 可重复迁移 | R |
无 | 每次 checksum 变化时重新执行 | 视图、存储过程、函数定义 |
| 撤销迁移 | U |
有(对应版本化迁移) | 手动触发 | 回滚特定版本(仅 Teams 版支持) |
| Java 迁移 | V / R |
有 / 无 | 同对应类型 | 复杂数据转换、调用外部 API |