数据库迁移工具排行:Liquibase与Flyway实战指南
数据库迁移工具的选择与切换,往往是团队里争议最大的技术决策之一。Liquibase 和 Flyway 各有拥趸,但真正让人头疼的,不是选哪个,而是——两个都在用。当你需要把 GitHub Copilot 相关的元数据从旧环境迁移到新库时,要是这两套工具对变更历史的认知不一致,那麻烦就大了:轻则重复执行脚本,重则直接跳过关键迁移。
所以,动手之前,先搞清楚数据库当前是什么状态。连接目标库,跑一下 SELECT * FROM databasechangelog;(Liquibase 的专属表)或者 SELECT * FROM flyway_schema_history;(Flyway 那套)。重点看三件事:表存不存在、是不是空的、最新记录的 ID 或 installed_rank 有没有断档。如果两张表都不存在,那好办,直接编写脚本初始化就行;但要是其中一张已经有记录,另一张却是空的,千万别手滑去清空那个有数据的表——版本偏移一旦发生,几乎没有回滚的可能。
统一变更起点:导出并重写初始快照
要让两个工具从同一个起点出发,有三种主流做法可以选。
方法一:用 Liquibase 生成基准脚本
执行 liquibase generate-changelog --outputFile=init.xml --diffTypes=tables,columns,它能导出当前数据库中所有表的结构,生成一份 XML 快照。注意,这个快照包含了完整的建表信息,后续工作都基于它展开。
方法二:用 Flyway 创建 V1__init.sql
在 src/main/resources/db/migration/ 目录下新建一个文件,手动写出 CREATE TABLE 语句。这里有个容易忽略的细节:字段类型必须跟数据库实际的 DDL 严格一致。比如 PostgreSQL 里用 TEXT 就别偷懒写成 VARCHAR(255),否则后续的 diff 工具会误判成一次变更,引发一系列不必要的修复操作。
方法三:跨工具同步元数据
如果你已经有 Liquibase 生成的 init.xml,可以把里面每个 -- flyway:sql 注释行,否则 Flyway 会直接跳过解析。
编写双兼容的增量迁移脚本
做好基础快照后,剩下的就是增量脚本了。这一步考验的不仅是技术细节,更是对两个工具语法的熟悉程度。
第一步:为 Liquibase 准备 changeset
在 changelog-master.xml 中新增一个变更集,比如建立一个 copilot_session 表:
第二步:为 Flyway 生成对应 SQL
运行 liquibase --changeLogFile=changelog-master.xml generate-sql --outputFile=V3__add_copilot_session_table.sql,Liquibase 会帮你把 changeset 转译成标准 SQL 文件。
第三步:校验并修正 SQL 兼容性
打开生成的 SQL,仔细检查有没有 Liquibase 特有的语法,比如 ADD COLUMN IF NOT EXISTS。Flyway 不支持这种写法,必须删掉 IF NOT EXISTS,并且确保目标库中确实没有该列——因为一旦执行失败,Flyway 没有回滚机制,后续所有脚本都会卡住。
第四步:注入双标记头
在 V3__add_copilot_session_table.sql 文件的最顶部,添加两行注释:
-- liquibase formatted sql
-- flyback:sql
这两行的顺序不能颠倒。Liquibase 只认第一行,Flyway 只认第二行,一个错的顺序可能导致整个脚本流被彻底跳过。很多踩坑的人,问题就出在这两行上。