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 个步骤,整个过程是原子性的:要么全部成功,要么全部回滚(在支持事务的数据库中)。
- 检查状态:Flyway 连接数据库,检查
flyway_schema_history表是否存在。如果不存在,则自动创建。 - 扫描脚本:Flyway 扫描配置的迁移脚本路径(如
classpath:db/migration),获取所有可用的迁移脚本列表。 - 计算差异:将扫描到的脚本列表与
flyway_schema_history表中的记录进行比对,确定哪些脚本是待执行的(版本号高于当前最大已执行版本号,且校验和未变)。 - 锁定数据库:为防止集群环境下的并发迁移,Flyway 会在数据库层面获取一个排他锁(基于
flyway_schema_history表)。 - 执行迁移:按版本号升序依次执行待迁移的脚本。每个脚本执行成功后,立即向
flyway_schema_history表插入一条成功记录。 - 释放锁:所有迁移脚本执行完毕后,释放数据库锁,完成本次迁移。
下面的 SVG 流程图直观展示了 Flyway 从连接到执行完成的完整迁移流程:
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 时间戳是否符合预期。这是验证迁移脚本正确性的第一道防线。