3. Flyway 核心概念:迁移、校验、基线、撤销与重复迁移

Flyway 作为数据库版本控制工具,其核心操作围绕五个关键概念展开。理解这些概念是设计可靠迁移架构的基础。本章将逐一剖析每个概念的定义、触发时机、适用场景及最佳实践。

3.1 迁移(Migration)

迁移是 Flyway 管理数据库变更的基本单元,本质是一个包含 SQL 或 Java 代码的版本化文件。Flyway 通过扫描指定路径下的迁移文件,按版本号顺序依次执行,从而将数据库从当前状态演进到目标状态。

迁移分为两种类型:

类型 命名模式 特点 典型场景
版本化迁移 V<版本号>__<描述>.sql 每个版本仅执行一次,不可重复执行 DDL 变更、新增表、修改字段
重复迁移 R__<描述>.sql 每次校验时重新执行,内容可覆盖 视图、存储过程、函数、物化视图
命名规范要点:
  • 版本号建议使用整数递增(如 V1__init.sql、V2__add_users.sql),避免使用小数点导致排序混乱。
  • 描述部分使用下划线分隔单词,保持语义清晰。
  • 迁移文件一旦提交到版本控制,禁止修改内容,否则会导致校验失败。

3.2 校验(Validate)

校验是 Flyway 确保数据库状态与迁移历史一致性的核心机制。每次执行 flyway migrate 或 flyway validate 命令时,Flyway 会对比已应用的迁移文件与当前文件系统中的迁移文件,检测是否存在篡改、缺失或版本冲突。

校验规则包括:

  • 校验和(Checksum)匹配:对已执行的迁移文件重新计算校验和,与 flyway_schema_history 表中记录的校验和对比。不一致则报错。
  • 版本唯一性:检查所有迁移文件的版本号是否重复。
  • 描述一致性:已执行迁移的描述必须与文件系统中的描述一致。
  • 迁移顺序:确保文件系统中的迁移版本顺序与历史记录中的执行顺序一致。
常见校验失败场景:
  • 开发人员修改了已提交的迁移文件内容。
  • 多人同时提交了相同版本号的迁移文件。
  • 迁移文件被删除或重命名。
解决方案:永远不要修改已执行的迁移文件,如需修正,应创建新的迁移版本。
Flyway 校验(Validate)流程 文件系统 V1__init.sql V2__add_users.sql 校验引擎 Checksum 对比 版本唯一性检查 flyway_schema_history 已执行记录 校验和、版本号 校验结果 通过 / 失败 校验失败时,migrate 命令 会立即终止执行

3.3 基线(Baseline)

基线用于将 Flyway 引入一个已有数据库实例。当数据库已存在部分表或数据时,通过设置基线版本,Flyway 会将该版本标记为“已应用”,从而跳过对已有结构的迁移,只管理基线版本之后的变更。

基线操作的核心参数:

参数 说明 默认值
flyway.baseline-version 指定基线版本号,该版本及之前的迁移被视为已执行 1
flyway.baseline-description 基线版本的描述信息 Baseline
flyway.baseline-on-migrate 当目标数据库非空且无历史表时,自动执行基线 false
基线最佳实践:
  • 在项目初期就引入 Flyway,避免后期需要基线操作。
  • 基线版本号应低于第一个迁移文件的版本号,例如基线设为 0,第一个迁移从 V1__ 开始。
  • 执行基线前,务必确认数据库当前状态与基线描述一致,避免状态漂移。

3.4 撤销(Undo)

撤销操作用于回滚已执行的版本化迁移。Flyway 通过执行与迁移文件对应的撤销文件(命名模式为 U<版本号>__<描述>.sql)来撤销变更。撤销文件需要开发者手动编写,Flyway 不会自动生成。

撤销的局限性:

  • 非默认功能:Flyway Teams 版(商业版)才支持撤销,社区版不提供此功能。
  • 手动维护成本高:每个迁移文件都需要对应的撤销文件,且撤销逻辑必须精确还原。
  • 不推荐用于生产环境:撤销可能导致数据丢失或约束冲突,官方建议使用向前迁移(创建新的迁移来修复问题)替代撤销。
撤销 vs 向前迁移:
对比维度 撤销(Undo) 向前迁移(Forward Migration)
安全性 低,可能丢失数据 高,保留完整变更历史
维护成本 高,需维护成对文件 低,只需新增迁移
团队协作 易冲突,版本线复杂 线性演进,清晰可控
Flyway 版本 仅 Teams 版 所有版本

3.5 重复迁移(Repeatable Migration)

重复迁移是一种特殊类型的迁移,其文件命名以 R__ 开头,不包含版本号。每次执行 flyway migrate 时,如果重复迁移文件的内容(校验和)发生变化,Flyway 会重新执行该迁移。

重复迁移的典型用途:

  • 视图(View):视图定义经常需要调整,使用重复迁移可以随时更新。
  • 存储过程(Stored Procedure):业务逻辑变更时,直接修改迁移文件即可。
  • 函数(Function):与存储过程类似,适合频繁迭代。
  • 物化视图(Materialized View):刷新逻辑或查询结构调整。
  • 参考数据(Reference Data):需要定期更新的静态数据。
重复迁移执行顺序:
  1. Flyway 先执行所有未应用的版本化迁移(按版本号升序)。
  2. 然后执行所有校验和发生变化的重复迁移(按文件名排序)。
  3. 重复迁移的执行顺序在 flyway_schema_history 表中记录为 installed_rank,但版本号字段为空。
迁移类型对比:版本化迁移 vs 重复迁移 版本化迁移 命名:V<版本号>__<描述>.sql 执行次数:每个版本仅一次 内容变更:禁止修改,需新建版本 典型场景:DDL、DML 变更 重复迁移 命名:R__<描述>.sql 执行次数:校验和变化时重新执行 内容变更:直接修改文件即可 典型场景:视图、存储过程、函数 执行顺序 先执行所有未应用的版本化迁移 → 再执行校验和变化的重复迁移 flyway_schema_history:版本化迁移记录版本号,重复迁移版本号字段为空

3.6 核心概念关系总结

五个核心概念在 Flyway 迁移生命周期中相互配合,形成完整的数据库版本管理闭环:

概念 触发时机 核心作用 依赖关系
迁移 migrate 命令 执行数据库变更 校验通过后执行
校验 migrate / validate 命令 确保迁移文件未被篡改 依赖历史表记录
基线 baseline 命令 初始化已有数据库 在首次 migrate 前执行
撤销 undo 命令(Teams 版) 回滚版本化迁移 依赖对应的撤销文件
重复迁移 migrate 命令(校验和变化时) 管理可重复变更对象 在版本化迁移之后执行
架构设计建议:
  • 将 DDL 变更(建表、加字段)放在版本化迁移中,确保每个变更可追溯。
  • 将视图、存储过程等逻辑对象放在重复迁移中,降低维护成本。
  • 在 CI/CD 流水线中强制开启校验,防止篡改历史迁移文件。
  • 生产环境禁用撤销,使用向前迁移策略处理回滚需求。