数据库迁移工具入门:Flyway与Liquibase
说到数据库版本管理,市面上最主流的两个工具就是 Flyway 和 Liquibase。我这些年大大小小的项目都用过它们,说实话,各有各的脾气。今天咱们就好好聊聊这两个工具的核心概念,以及怎么选型。
你可能会问:为什么不用手动执行 SQL 脚本?嗯,我刚开始带团队时也这么干过。结果呢?有一次上线前,测试环境和生产环境的表结构差了三个字段,差点酿成事故。从那以后,我再也不敢轻视数据库版本管理了。
核心观点:数据库迁移工具的核心价值,就是把数据库 schema 的变化像代码一样纳入版本控制,让每一次变更都可追溯、可回滚、可复现。
Flyway 核心概念
Flyway 的理念很简单,就一句话:用版本号管理 SQL 脚本。它把每个数据库变更都看作一次"迁移",每个迁移文件都有一个唯一的版本号。
我个人习惯把 Flyway 比作"数据库的 Git"。你想想看,Git 用 commit id 管理代码版本,Flyway 用版本号管理数据库版本。道理是相通的。
Flyway 的迁移文件命名规则
Flyway 对文件命名有严格的要求。格式如下:
前缀 + 版本号 + 分隔符 + 描述 + 后缀
示例:
V1__create_user_table.sql
V2__add_email_column.sql
V3__create_order_table.sql
这里要注意几点:
- 前缀:
V代表版本化迁移,U代表撤销迁移,R代表可重复迁移 - 版本号:可以是数字,也可以用点号分隔,比如
V1.1__、V2.0.1__ - 分隔符:固定两个下划线
__ - 描述:简短说明,用下划线代替空格
我曾经踩过的坑:有一次我把版本号写成了 V1.0.0__init.sql,结果 Flyway 把 1.0.0 解析成了三个数字,导致后续 V1.0.1 的排序出了问题。后来我统一改用整数版本号,再也没出过这种问题。
Flyway 的工作流程
Flyway 会在数据库中创建一张元数据表(默认叫 flyway_schema_history),用来记录每次迁移的执行情况。每次启动时,它会做这几件事:
- 检查元数据表是否存在,不存在则创建
- 扫描文件系统中的迁移脚本
- 对比已执行的脚本和待执行的脚本
- 按版本号顺序执行未执行的脚本
- 记录执行结果到元数据表
说白了,Flyway 就是个"按顺序执行脚本"的工具。它不关心你脚本里写了什么,只关心版本号对不对、有没有重复执行。
Liquibase 核心概念
Liquibase 的思路和 Flyway 不太一样。它用 变更集(ChangeSet) 来描述数据库变更,每个变更集都有一个唯一的标识符。
我在项目中遇到过这样一个场景:需要同时支持 MySQL 和 PostgreSQL。用 Flyway 的话,得维护两套 SQL 脚本。但 Liquibase 的抽象能力就派上用场了——它可以用 XML、YAML、JSON 等格式描述变更,然后自动生成对应数据库的 SQL。
Liquibase 的变更集
一个典型的 Liquibase 变更集长这样:
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<changeSet id="1" author="zhangsan">
<createTable tableName="user">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
<column name="email" type="varchar(200)"/>
</createTable>
</changeSet>
<changeSet id="2" author="lisi">
<addColumn tableName="user">
<column name="phone" type="varchar(20)"/>
</addColumn>
</changeSet>
</databaseChangeLog>
每个 changeSet 由 id 和 author 共同唯一标识。Liquibase 会记录哪些变更集已经执行过,下次只执行新增的。
Liquibase 的追踪表
和 Flyway 类似,Liquibase 也会在数据库中创建两张元数据表:
DATABASECHANGELOG:记录已执行的变更集DATABASECHANGELOGLOCK:用于分布式环境下的锁机制,防止并发执行
小技巧:Liquibase 支持 context 属性,可以按环境执行不同的变更集。比如开发环境执行测试数据插入,生产环境跳过。我在做 CI/CD 流水线时经常用这个功能。
工具选型对比
好了,两个工具的核心概念都讲完了。接下来咱们做个对比,帮你选型时有个参考。
| 对比维度 | Flyway | Liquibase |
|---|---|---|
| 核心理念 | 版本号驱动的 SQL 脚本管理 | 变更集驱动的数据库抽象 |
| 脚本格式 | 纯 SQL | XML/YAML/JSON + SQL |
| 学习曲线 | 低,会 SQL 就能用 | 中,需要学习 DSL 语法 |
| 数据库兼容性 | 依赖 SQL 方言,切换数据库需改脚本 | 内置抽象层,切换数据库较方便 |
| 回滚支持 | 需手动编写撤销脚本(U 前缀) | 内置回滚,可自动生成 |
| 分布式锁 | 不支持 | 支持,通过 DATABASECHANGELOGLOCK 表 |
| 社区生态 | Spring Boot 原生集成,社区活跃 | 企业级功能丰富,文档完善 |
我个人的选型建议
说实话,没有银弹。选哪个取决于你的团队和项目情况:
- 团队 SQL 功底扎实,项目只用一种数据库 → 选 Flyway。简单直接,上手快。
- 需要支持多种数据库,或者有复杂的回滚需求 → 选 Liquibase。抽象层能省不少事。
- Spring Boot 项目 → Flyway 集成更自然,几乎零配置。
- 企业级项目,对变更审计、权限控制有要求 → Liquibase 的 Pro 版本提供了这些功能。
我的经验:小团队、快速迭代的项目,我倾向于 Flyway。大团队、多数据库、需要严格变更管控的项目,Liquibase 更合适。但不管选哪个,都比手动执行 SQL 强一百倍。
知识体系总览
下面这张图帮你梳理本章的核心知识点:
总结
Flyway 和 Liquibase 都是成熟的数据库迁移工具,没有的好坏。Flyway 胜在简单直接,适合 SQL 功底扎实的团队;Liquibase 胜在抽象能力强,适合多数据库场景。
我个人建议:先选一个用起来,比纠结选哪个更重要。等你用熟了,自然就知道什么时候该换、该换什么。毕竟,工具是为人服务的,不是反过来。