3、Flyway 工作原理解析:迁移状态跟踪与执行流程

Flyway 作为一款数据库版本控制工具,其核心能力在于自动跟踪每一次迁移脚本的执行状态,并确保数据库 Schema 的版本与代码仓库中的迁移脚本保持同步。理解 Flyway 的工作原理,是正确配置迁移参数和进行冒烟检查的基础。

3.1 Flyway 如何跟踪迁移状态

Flyway 通过一个专用的元数据表来记录所有已执行的迁移记录。默认情况下,该表名为 flyway_schema_history,但可以通过配置参数 flyway.table 进行自定义。

当 Flyway 首次对目标数据库执行迁移操作时,它会自动创建这张表。每次成功执行一个迁移脚本后,Flyway 都会在该表中插入一条记录,包含脚本的版本号、描述、校验和、执行时间等信息。在下一次迁移时,Flyway 会读取这张表,对比文件系统中的迁移脚本,从而决定哪些脚本需要执行、哪些已经执行过、哪些需要回滚(如果配置了回滚支持)。

关键原则:Flyway 的迁移状态完全依赖于 flyway_schema_history 表。如果该表被意外删除或损坏,Flyway 将无法感知已执行的迁移,可能导致重复执行或状态混乱。因此,在生产环境中,禁止手动操作该表。

3.2 schema_history 表结构详解

flyway_schema_history 表是 Flyway 的“大脑”,其结构设计严谨,用于支撑版本校验、重复执行检测和迁移回滚。下表列出了该表的核心字段及其作用:

字段名 类型 说明
installed_rank INT 执行顺序号,从 1 开始递增,用于确定迁移的执行顺序。
version VARCHAR 迁移脚本的版本号,如 1.0、2.1.3。未版本化的重复迁移(Repeatable)该字段为 null。
description VARCHAR 迁移脚本的描述信息,通常从文件名中提取(如 V1__init.sql 中的 init)。
type VARCHAR 迁移类型:SQL(SQL 脚本)、JDBC(Java 代码迁移)、SPRING_JDBC 等。
script VARCHAR 迁移脚本的文件名或 Java 类名。
checksum INT 脚本内容的校验和(CRC32 或 MD5),用于检测脚本是否被篡改。
installed_by VARCHAR 执行迁移的数据库用户。
installed_on TIMESTAMP 迁移执行完成的时间戳。
execution_time INT 迁移脚本执行所花费的毫秒数。
success BOOLEAN 迁移是否成功:1 表示成功,0 表示失败。失败的迁移记录会被保留,用于后续排查。
校验和(checksum)的重要性:Flyway 在每次迁移时都会重新计算已执行脚本的校验和,并与 flyway_schema_history 表中的记录进行比对。如果发现校验和不一致(例如有人手动修改了已迁移的脚本文件),Flyway 会抛出异常并阻止迁移,从而防止数据不一致。这是 Flyway 保证迁移脚本不可变的核心机制。

3.3 迁移执行流程

Flyway 的迁移执行流程可以概括为以下 6 个步骤,整个过程是原子性的:要么全部成功,要么全部回滚(在支持事务的数据库中)。

  1. 检查状态:Flyway 连接数据库,检查 flyway_schema_history 表是否存在。如果不存在,则自动创建。
  2. 扫描脚本:Flyway 扫描配置的迁移脚本路径(如 classpath:db/migration),获取所有可用的迁移脚本列表。
  3. 计算差异:将扫描到的脚本列表与 flyway_schema_history 表中的记录进行比对,确定哪些脚本是待执行的(版本号高于当前最大已执行版本号,且校验和未变)。
  4. 锁定数据库:为防止集群环境下的并发迁移,Flyway 会在数据库层面获取一个排他锁(基于 flyway_schema_history 表)。
  5. 执行迁移:按版本号升序依次执行待迁移的脚本。每个脚本执行成功后,立即向 flyway_schema_history 表插入一条成功记录。
  6. 释放锁:所有迁移脚本执行完毕后,释放数据库锁,完成本次迁移。

下面的 SVG 流程图直观展示了 Flyway 从连接到执行完成的完整迁移流程:

Flyway 迁移执行流程图 Flyway 迁移执行流程 1. 连接数据库 2. 检查/创建 schema_history 表 3. 扫描迁移脚本 4. 计算差异(待执行列表) 5. 锁定数据库 6. 执行迁移并记录 7. 释放锁

3.4 迁移执行的关键特性

  • 版本顺序执行:Flyway 严格按照版本号升序执行迁移脚本,确保数据库 Schema 的变更历史是线性且可追溯的。
  • 幂等性保障:对于可重复迁移(Repeatable Migration,文件名如 R__my_view.sql),Flyway 会在每次迁移时重新执行,但仅当脚本内容发生变化(校验和改变)时才会执行。
  • 失败处理:如果某个迁移脚本执行失败,Flyway 会立即停止迁移,并在 flyway_schema_history 表中记录失败状态(success=0)。此时数据库处于“脏”状态,需要手动修复或回滚后才能继续。
  • 集群安全:通过数据库锁机制,Flyway 确保在集群环境中,同一时间只有一个节点执行迁移操作,避免并发冲突。
实践要点:在冒烟检查环节,可以通过查询 flyway_schema_history 表来验证迁移是否按预期执行。例如,检查 success 字段是否全部为 1,以及 installed_on 时间戳是否符合预期。这是验证迁移脚本正确性的第一道防线。