1. Flyway 概述
1.1 Flyway 是什么
Flyway 是一款开源的数据库版本控制工具,采用 “约定优于配置” 的设计哲学,将数据库脚本的变更纳入版本管理,使数据库的演进与应用程序代码的迭代保持同步。它通过扫描指定路径下的迁移脚本,自动计算当前数据库版本与目标版本之间的差异,并按顺序执行未应用的迁移,从而确保开发、测试、生产环境的数据库结构始终一致。
核心定位:Flyway 不是数据库客户端,而是一个数据库迁移引擎。它不关心 SQL 的具体内容,只关心迁移脚本的版本号、顺序和校验和,从而保证迁移过程的可重复性和可追溯性。
Flyway 支持 Java、Maven、Gradle、命令行等多种集成方式,可无缝嵌入 Spring Boot、Quarkus 等主流框架,是微服务架构中数据库持续交付的标准组件之一。
1.2 核心概念
Flyway 定义了三种迁移类型,分别对应不同的变更场景:
| 迁移类型 | 命名格式 | 执行时机 | 校验和 | 典型场景 |
|---|---|---|---|---|
| 版本化迁移 | V<版本号>__<描述>.sql |
按版本号升序执行,每个版本仅执行一次 | 记录校验和,禁止修改已执行脚本 | 建表、加字段、创建索引等结构性变更 |
| 可重复迁移 | R__<描述>.sql |
每次校验和发生变化时重新执行 | 校验和变化即触发重新执行 | 视图、存储过程、函数、物化视图 |
| 撤销迁移 | U<版本号>__<描述>.sql |
手动触发,回退指定版本 | 与对应版本化迁移配对 | 紧急回滚、开发环境重置 |
实践建议:版本化迁移是生产环境的主力,每个迁移脚本应只包含一个原子变更(如一张表或一个索引),便于回滚和问题定位。可重复迁移适合管理视图和函数,但要注意其执行顺序不受版本号控制,如果视图之间存在依赖,需在脚本内通过
DROP IF EXISTS + CREATE 的方式保证幂等性。
Flyway 通过一张名为 flyway_schema_history 的元数据表来记录所有已执行的迁移记录,包括版本号、描述、脚本类型、校验和、执行时间等关键信息。每次启动时,Flyway 会对比文件系统中的脚本与元数据表中的记录,决定哪些脚本需要执行。
1.3 与传统数据库脚本管理的对比
传统数据库脚本管理通常依赖 DBA 手动执行或通过简单的 SQL 文件归档,存在以下痛点:
- 版本混乱:脚本文件散落在不同目录,缺乏统一的版本标识,难以追溯哪个脚本在哪个环境执行过。
- 重复执行风险:同一脚本在多个环境重复执行,导致
ORA-00955: name is already used by an existing object等错误。 - 协作困难:多人并行开发时,脚本合并冲突频繁,且无法自动检测依赖顺序。
- 回滚无标准:回滚操作依赖人工编写反向 SQL,容易遗漏或出错。
Flyway 通过版本化、校验和、元数据表等机制,从根本上解决了上述问题。以下对比表可以直观展示差异:
| 对比维度 | 传统脚本管理 | Flyway 管理 |
|---|---|---|
| 版本标识 | 文件名或注释,无强制规范 | 版本号 + 描述,严格升序 |
| 执行记录 | 无或手动记录 | 自动写入 flyway_schema_history |
| 重复执行防护 | 依赖人工判断或 IF NOT EXISTS |
校验和 + 已执行标记,自动跳过 |
| 回滚能力 | 手动编写反向 SQL | 撤销迁移脚本,版本配对回滚 |
| 多环境一致性 | 依赖人工同步 | 脚本即配置,自动同步 |
| 协作冲突 | 频繁冲突,手动解决 | 版本号隔离,冲突可检测 |
常见误区:不要将 Flyway 与 Liquibase 混淆。Flyway 使用原生 SQL 脚本,学习成本低;Liquibase 使用 XML/YAML/JSON 描述变更,更灵活但语法更重。选择哪个取决于团队对 SQL 的掌控力和对声明式配置的偏好。在微服务场景下,Flyway 的轻量级和 Spring Boot 原生集成使其更受欢迎。