SQL 数据库迁移工具 Flyway vs Liquibase 的版本管理与回滚能力对比

1次阅读

flyway不支持任意回滚,仅能通过新增逆向脚本实现有限回退;liquibase需在changeset中显式定义rollback逻辑,支持多种声明方式但依赖人工编写;二者均要求数据库处于干净状态,回滚非万能,须结合蓝绿发布等更可靠方案。

SQL 数据库迁移工具 Flyway vs Liquibase 的版本管理与回滚能力对比

Flyway 的版本号是严格递增的,不支持任意回滚

Flyway 把迁移看作单向演进过程,flyway migrate 执行后,schema_version 表里只记录已应用的版本和状态,没有“回退逻辑”的存储位置。它默认不提供 flyway undo 或类似命令——这不是遗漏,而是设计取舍。

常见错误现象:flyway repair 被误当成回滚用;或手动删 schema_version 行再重跑,结果触发校验失败(checksum mismatch)。

  • 真正能用的“回退”只有:写一个新 V2__rollback_to_v1.sql 迁移脚本,显式执行逆向操作(比如 DROP column 改成 ADD COLUMN
  • 如果用了 flyway clean,必须确保数据库可清空——生产环境禁用
  • 社区版完全不支持 undo;Pro 版虽有 flyway undo,但要求所有迁移脚本带 undo 配对,且只支持上一个版本(不能跳回 V1 → V3)

Liquibase 的 rollback 命令依赖 changelog 中的 rollback 属性

Liquibase 默认也不自动保存反向操作,它的 rollback 能力不是开箱即用的,而是靠你在每个 changeSet 里显式声明怎么撤回。

使用场景:你改了表结构、插了测试数据、甚至调了存储过程,都得自己写清楚“怎么撤销”。否则 liquibase rollbackCount 1 会直接报错:Cannot rollback changeset: no rollback statement provided

  • 支持三种回滚方式:内联 <rollback>SQL</rollback>、引用 rollbackScript 文件、或用内置标签如 <dropcolumn></dropcolumn>(它自带逆操作)
  • rollback 不检查实际数据状态,只按 changelog 执行——如果中间有人手动改库,rollback 可能失败或产生脏数据
  • xml/YAML/json 格式都支持 rollback 定义,但 SQL 格式(.sql changelog)只能靠 --rollback 注释块,易被忽略或格式写错

两者对“重复执行”和“版本冲突”的处理逻辑完全不同

Flyway 靠文件名哈希值做校验,Liquibase 靠 id/author/filepath 三元组加 checksum。这导致它们在协作开发、分支合并、CI 重跑时出问题的方式不一样。

常见错误现象:开发 A 提交 V2__add_user_table.sql,开发 B 同时提交 V2__create_audit_log.sql —— Flyway 直接报错“duplicate version”,Liquibase 则可能让两个 V2 共存(只要 id 不同),但上线时顺序不确定,引发依赖错误。

  • Flyway 要求版本号全局唯一且递增,适合强管控流程;Liquibase 允许并行开发,但需要团队约定 authorid 规范
  • Flyway 的 repair 是为修复 checksum 不一致而设,不是为解决冲突;Liquibase 的 changelogSync 可把现有 DDL 记录为已执行,但不会生成 rollback
  • CI 环境中,Flyway 更怕“本地多跑一次”,Liquibase 更怕“changelog 文件被覆盖丢失 rollback 块”

回滚能力不等于线上故障恢复能力

不管是 flyway undo 还是 liquibase rollback,都假设数据库处于“干净迁移态”——没手工改过结构、没绕过工具插过数据、没跨版本跳迁。现实里这三个条件常不满足。

  • 真正高可用场景下,回滚只是兜底选项;更可靠的是蓝绿发布、影子表切换、或应用层兼容旧结构
  • Liquibase 的 rollback 脚本如果含 delete FROM,执行后无法还原数据;Flyway 的“重写 V2 为逆向 SQL”也一样不可逆
  • 所有回滚操作都应先在预发环境完整验证,尤其注意外键约束、索引失效、序列值偏移等隐性影响
text=ZqhQzanResources