1. 简介
本文将介绍几种使用 Flyway 回滚数据库迁移的方案。对于线上变更频繁的系统来说,可逆的数据库变更是一项刚需,而 Flyway 本身并不原生支持回滚(Community 版本),但我们可以通过一些方式“模拟”或“真正”实现回滚。
⚠️ 注意:本文演示使用的是命令行版本的 Flyway,但核心逻辑同样适用于 Java API、Maven 插件等集成方式。
2. 通过标准迁移模拟回滚
最简单粗暴的方式,就是写一个“反向 SQL”作为新的迁移脚本。虽然 Flyway 不支持自动回滚,但我们可以手动补一个“撤回”脚本。
2.1 创建初始迁移
我们先创建一个 book
表作为初始结构。新建迁移文件:
-- V1_0__create_book_table.sql
create table book (
id numeric,
title varchar(128),
author varchar(256),
constraint pk_book primary key (id)
);
执行迁移:
./flyway migrate
✅ 此时 book
表已创建,Flyway 的 flyway_schema_history
表中记录了该版本。
2.2 模拟回滚操作
假设我们发现这个表建错了,需要“回滚”。由于 Flyway Community 不支持 undo
,我们只能再写一个反向操作:
-- V2_0__drop_table_book.sql
drop table book;
再次执行迁移:
./flyway migrate
查看迁移历史:
./flyway info
输出结果:
+-----------+---------+-------------------+------+---------------------+---------+
| Category | Version | Description | Type | Installed On | State |
+-----------+---------+-------------------+------+---------------------+---------+
| Versioned | 1.0 | create book table | SQL | 2020-08-29 16:07:43 | Success |
| Versioned | 2.0 | drop table book | SQL | 2020-08-29 16:08:15 | Success |
+-----------+---------+-------------------+------+---------------------+---------+
🔍 重点观察:
- 两条记录都是
Versioned
类型,状态均为Success
- 没有体现“回滚”关系,审计日志中看不出 V2.0 是为了撤销 V1.0
- 从数据库角度看,表被删了,效果达到了,但缺乏可追溯性
✅ 优点:简单直接,兼容所有 Flyway 版本
❌ 缺点:破坏了版本递增语义,审计困难,容易踩坑(比如重复执行)
3. 使用 Flyway Undo(商业版功能)
如果你使用的是 Flyway Pro 或 Enterprise 版本,可以使用官方提供的 undo
命令。这才是真正的、结构化的回滚机制。
⚠️ 重要提醒:Flyway Undo 是商业功能,Community Edition 不可用。
3.1 创建迁移与反向迁移文件
我们需要为每个正向迁移配一个对应的“反向迁移”文件。
-- V1_0__create_book_table.sql
create table book (
id numeric,
title varchar(128),
author varchar(256),
constraint pk_book primary key (id)
);
对应反向操作:
-- U1_0__create_book_table.sql
drop table book;
📌 命名规范:
- 正向迁移前缀为
V
- 反向迁移前缀为
U
- 版本号和描述需完全一致,Flyway 才能自动匹配
3.2 执行迁移并验证状态
先查看当前迁移状态:
./flyway -pro info
输出:
+-----------+---------+-------------------+------+--------------+---------+----------+
| Category | Version | Description | Type | Installed On | State | Undoable |
+-----------+---------+-------------------+------+--------------+---------+----------+
| Versioned | 1.0 | create book table | SQL | | Pending | Yes |
+-----------+---------+-------------------+------+--------------+---------+----------+
✅ 注意 Undoable: Yes
字段,说明 Flyway 检测到了对应的 U
文件。
执行迁移:
./flyway migrate
迁移完成后,数据库中会出现 book
表:
List of relations
Schema | Name | Type | Owner
--------+-----------------------+-------+----------
public | book | table | flyway_user
public | flyway_schema_history | table | flyway_user
(2 rows)
3.3 执行回滚操作
现在我们可以使用 undo
命令安全回滚:
./flyway -pro undo
回滚成功后,再次查看状态:
./flyway -pro info
输出:
+-----------+---------+-------------------+----------+---------------------+---------+----------+
| Category | Version | Description | Type | Installed On | State | Undoable |
+-----------+---------+-------------------+----------+---------------------+---------+----------+
| Versioned | 1.0 | create book table | SQL | 2020-08-22 15:48:00 | Undone | |
| Undo | 1.0 | create book table | UNDO_SQL | 2020-08-22 15:49:47 | Success | |
| Versioned | 1.0 | create book table | SQL | | Pending | Yes |
+-----------+---------+-------------------+----------+---------------------+---------+----------+
🔍 关键变化:
- 多出一条
Category: Undo
的记录 - 原
Versioned
记录状态变为Undone
- 审计日志清晰体现“谁被回滚了”,可追溯性强 ✅
⚠️ 注意限制:
undo
要求原始迁移必须完整成功执行,中途失败的迁移无法回滚- 不支持对
repeatable
迁移进行 undo - 需要额外维护
U
脚本,增加维护成本
4. 总结
方式 | 是否需要商业版 | 审计可追溯 | 使用难度 | 推荐场景 |
---|---|---|---|---|
✅ 模拟回滚(V2.0) | 否 | ❌ 弱 | 简单 | 小项目、临时修复 |
✅ Flyway Undo | 是 | ✅ 强 | 中等 | 生产环境、需审计 |
📌 核心建议:
- 如果你在生产环境使用 Flyway,且对变更审计有要求,强烈建议升级到 Pro 或 Enterprise 版本,使用
undo
功能。 - 若只能用 Community 版,务必规范命名反向迁移脚本(如
V2_1__undo_create_book_table.sql
),并通过文档或注释标明其用途,避免后续维护踩坑。
🔄 数据库迁移的本质是“版本控制”,而回滚能力是版本控制的基石。选择合适的方式,才能让 DB 变更像代码一样安全可控。