1. 概述
在上篇文章中,我们介绍了 Liquibase 作为数据库架构和数据管理工具的使用方法。
本文将深入探讨 Liquibase 的回滚功能——如何撤销已执行的数据库变更操作。⚠️ 这在生产级系统中是至关重要的能力。
2. Liquibase 迁移的分类
Liquibase 操作分为两类,对应不同的回滚语句生成方式:
- 自动回滚:迁移操作能明确生成回滚步骤
- 手动回滚:需要手动编写回滚命令,因为迁移指令无法自动确定回滚语句
例如:
✅ 创建表操作的回滚是删除该表,这可以明确推导,因此能自动生成回滚语句
❌ 删除表操作的回滚无法自动生成,因为无法确定表被删除前的状态,必须手动提供回滚指令
3. 编写简单回滚语句
下面是一个创建表的变更集示例,包含自定义回滚语句:
<changeSet id="testRollback" author="baeldung">
<createTable tableName="baeldung_tutorial">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial"/>
</rollback>
</changeSet>
踩坑提示:虽然 Liquibase 会为
createTable
自动生成回滚语句,但这里我们手动覆盖了默认行为。
执行迁移命令:
mvn liquibase:update
执行回滚命令:
mvn liquibase:rollback
⚠️ 直接执行回滚会失败!必须指定以下三种限制条件之一:
-
rollbackTag
- 回滚到指定标签 -
rollbackCount
- 回滚指定数量的变更集 -
rollbackDate
- 回滚到指定时间点
3.1. 回滚到标签
为数据库状态打标签后,可回滚到该标签状态:
mvn liquibase:rollback -Dliquibase.rollbackTag=1.0
这将回滚标签 "1.0" 之后执行的所有变更集。
3.2. 按数量回滚
指定要回滚的变更集数量(例如回滚最近1个变更集):
mvn liquibase:rollback -Dliquibase.rollbackCount=1
3.3. 按日期回滚
回滚指定日期之后的所有变更:
mvn liquibase:rollback "-Dliquibase.rollbackDate=Jun 03, 2017"
日期格式需符合 ISO 标准或运行平台
DateFormat.getDateInstance()
的格式。
4. 变更集回滚选项
4.1. 多语句回滚
单个 <rollback>
标签可包含多个操作:
<changeSet id="multiStatementRollback" author="baeldung">
<createTable tableName="baeldung_tutorial2">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
</createTable>
<createTable tableName="baeldung_tutorial3">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial2"/>
<dropTable tableName="baeldung_tutorial3"/>
</rollback>
</changeSet>
4.2. 多回滚标签
变更集中可使用多个 <rollback>
标签,按出现顺序执行:
<changeSet id="multipleRollbackTags" author="baeldung">
<createTable tableName="baeldung_tutorial4">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
</createTable>
<createTable tableName="baeldung_tutorial5">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial4"/>
</rollback>
<rollback>
<dropTable tableName="baeldung_tutorial5"/>
</rollback>
</changeSet>
4.3. 引用其他变更集回滚
通过 changeSetId
和 changeSetAuthor
引用其他变更集的回滚逻辑,避免代码重复:
<changeSet id="referChangeSetForRollback" author="baeldung">
<dropTable tableName="baeldung_tutorial2"/>
<dropTable tableName="baeldung_tutorial3"/>
<rollback changeSetId="multiStatementRollback" changeSetAuthor="baeldung"/>
</changeSet>
4.4. 空回滚标签
使用空 <rollback/>
禁用自动回滚生成:
<changeSet id="emptyRollback" author="baeldung">
<createTable tableName="baeldung_tutorial">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback/>
</changeSet>
5. 回滚命令选项
5.1. 生成回滚脚本
生成回滚 SQL 而非直接执行:
-
rollbackSQL <tag>
- 回滚到指定标签的 SQL 脚本 -
rollbackToDateSQL <date/time>
- 回滚到指定时间的 SQL 脚本 -
rollbackCountSQL <value>
- 回滚指定步数的 SQL 脚本
示例:
mvn liquibase:rollbackCountSQL 2
5.2. 生成未来回滚脚本
生成将当前数据库回滚到未来状态的 SQL 脚本(适用于部署前的回滚预案):
mvn liquibase:futureRollbackSQL
5.3. 测试更新与回滚
执行完整迁移后立即回滚,用于验证变更集的正确性(不改变最终数据库状态):
mvn liquibase:updateTestingRollback
简单粗暴的测试方式:实际执行变更再回滚,确保操作可逆。
6. 总结
本文系统介绍了 Liquibase 回滚功能的核心概念和实用技巧,包括:
- 自动/手动回滚的适用场景
- 三种回滚限制方式(标签/数量/日期)
- 变更集中回滚语句的灵活配置
- 回滚脚本的生成与测试方法
完整代码示例可在 GitHub 获取。