Flyway 工作原理:迁移机制、版本号解析、校验与修复、基线版本

Flyway 的核心设计理念是“约定优于配置”,通过一套标准化的迁移文件命名规则和版本号解析逻辑,自动管理数据库模式的演进。理解其底层工作原理,是构建可靠数据库迁移架构的前提。

2.1 迁移机制:状态机与元数据表

Flyway 在目标数据库中维护一张名为 flyway_schema_history 的元数据表(默认名称,可配置),用于记录所有已执行的迁移记录。每次执行迁移时,Flyway 会执行以下状态机流程:

  1. 扫描:读取文件系统或类路径下的所有迁移脚本。
  2. 比对:将扫描到的脚本版本号与 flyway_schema_history 表中的已执行记录进行比对。
  3. 校验:对已执行过的脚本进行 checksum 校验,确保未被篡改。
  4. 执行:按版本号升序执行所有未应用的迁移脚本。
  5. 记录:将每次成功执行的迁移信息写入元数据表。
关键元数据字段:
  • installed_rank:执行顺序号
  • version:迁移版本号
  • description:迁移描述
  • type:迁移类型(SQL/JDBC/SPRING)
  • checksum:脚本内容的 CRC32 校验值
  • installed_on:执行时间戳
  • success:执行状态(1 成功 / 0 失败)
Flyway 迁移状态机流程 扫描迁移脚本 比对元数据表 校验 Checksum 执行迁移脚本 写入历史记录 是否已执行? 已执行,跳过 未执行

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:“这个数据库已经处于某个版本状态,不要尝试执行比这个版本更早的迁移脚本。”

基线版本的工作流程:

  1. 执行 flyway baseline 命令,指定基线版本号(如 1.0)。
  2. Flyway 在元数据表中插入一条基线记录,标记当前数据库状态。
  3. 后续执行 flyway migrate 时,只会执行版本号大于基线版本的迁移脚本。
基线版本与迁移范围示意 版本演进 基线前(已有数据库) 不执行迁移 基线 v1.0 V1.1 迁移脚本 V1.2 迁移脚本 ... 后续
基线版本最佳实践:
  • 基线版本号应等于或略低于当前数据库的实际版本状态。
  • 基线后立即执行一次 flyway migrate 验证基线设置是否正确。
  • 对于全新数据库,无需设置基线,Flyway 会自动从第一个迁移脚本开始执行。
  • 基线版本一旦设置,不建议修改;如需调整,应使用 flyway repair 重新对齐。

2.5 迁移类型对比总结

迁移类型 前缀 版本号 执行时机 典型用途
版本化迁移 V 有(如 1.0、2.1) 每个版本仅执行一次 表结构变更、索引创建、数据迁移
可重复迁移 R 无 每次 checksum 变化时重新执行 视图、存储过程、函数定义
撤销迁移 U 有(对应版本化迁移) 手动触发 回滚特定版本(仅 Teams 版支持)
Java 迁移 V / R 有 / 无 同对应类型 复杂数据转换、调用外部 API