- 开发环境、测试环境、生产环境数据结构各异
- 团队成员修改数据库后,其他人不知道最新变更
- 出现问题需要回滚,却找不到之前的SQL脚本
- 手动执行SQL脚本顺序错误,导致数据丢失
如果你经历过这些痛苦,那么今天介绍的 Liquibase 就是你的救星!它就像Git对于代码,让数据库变更变得可控、可追溯、可回滚。
Liquibase是什么?为什么它是数据库界的"Git"?
核心定位
Liquibase是一个开源的数据库版本控制工具,通过变更日志(Changelog)记录所有数据库变更,支持:
- 多数据库支持:MySQL、Oracle、PostgreSQL、SQL Server等60+数据库
- 版本控制:像Git一样管理数据库变更历史
- 自动回滚:出问题一键回退到安全版本
- 团队协作:多人修改不会互相干扰
与传统SQL脚本对比
| 对比维度 | 传统SQL脚本 | Liquibase |
|---|---|---|
| 执行顺序 | 手动维护,易出错 | 自动依赖,智能排序 |
| 回滚功能 | 需额外编写rollback脚本 | 内置回滚,一键搞定 |
| 变更追踪 | 难以查看历史记录 | DATABASECHANGELOG表完整记录 |
| 多环境同步 | 容易出现不一致 | 同一changelog保证一致 |
| 开发效率 | 重复工作多 | 自动化程度高 |
适用场景:这些项目建议用Liquibase!
强烈推荐场景
- 团队协作项目:多人同时开发,数据库变更频繁
- 微服务架构:多个服务需要独立管理数据库 schema
- 持续集成/持续部署(CI/CD):自动化流水线需要可靠的数据库迁移
- 多环境部署:开发、测试、生产环境需要保持一致
- 遗留系统重构:需要逐步迁移和回滚保障
不建议使用场景
- 小型项目(变更极少)
- 一次性脚本
- 对性能要求极致的场景(有少量开销)
快速上手:5分钟入门Liquibase
Step 1:添加Maven依赖
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.33.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
Step 2:Spring Boot配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db
username: root
password: 123456
liquibase:
change-log: classpath:db/changelog/db.changelog-master.yaml
enabled: true
Step 3:创建变更日志
主变更日志(db.changelog-master.yaml):
databaseChangeLog:
- include:
file: db/changelog/v1.0/changelog-v1.0.yaml
具体变更集(changelog-v1.0.yaml):
databaseChangeLog:
- changeSet:
id: 1
author: dev_team
changes:
- createTable:
tableName: user
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: username
type: varchar(50)
constraints:
nullable: false
Step 4:启动应用
# 启动Spring Boot应用,Liquibase自动执行变更
mvn spring-boot:run
执行日志示例:
2025-12-10 10:00:00.123 INFO --- [ main] liquibase.changelog
: Running Changeset: classpath:/db/changelog/v1.0/changelog-v1.0.yaml::1::dev_team
2025-12-10 10:00:00.456 INFO --- [ main] liquibase.changelog
: ChangeSet 1 ran successfully in 333ms
2025-12-10 10:00:00.789 INFO --- [ main] liquibase.lockservice
: Successfully released change log lock
查看数据库,你会发现user表已创建,且DATABASECHANGELOG表中记录了所有变更历史。
同类工具对比:为什么选Liquibase?
Flyway vs Liquibase
| 特性 | Flyway | Liquibase |
|---|---|---|
| 脚本格式 | 纯SQL | SQL、XML、YAML、JSON |
| 配置复杂度 | 简单 | 中等 |
| 回滚功能 | 不支持(需手动) | 内置支持 |
| 多数据库 | 需分别写SQL | 一套脚本适配多库 |
| 学习曲线 | 平缓 | 稍陡峭 |
结论:
- 小项目、纯SQL团队 → Flyway
- 大型项目、多数据库、需要回滚 → Liquibase
其他工具
- MyBatis Migrations:仅适用于MyBatis项目
- Alembic:Python生态,Java项目不适用
- 自定义脚本:维护成本高,不推荐
核心技能:如何快速编写变更集?
1. 常用变更类型
省略掉前面的:
databaseChangeLog.changeSet.changes标签
创建表:
- createTable:
tableName: order
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: user_id
type: bigint
constraints:
nullable: false
- column:
name: amount
type: decimal(10,2)
constraints:
nullable: false
添加字段:
- addColumn:
tableName: user
columns:
- column:
name: email
type: varchar(100)
创建索引:
- createIndex:
tableName: user
indexName: idx_user_username
columns:
- column:
name: username
插入数据:
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 1
- column:
name: code
value: 'ALIPAY'
- column:
name: name
value: '支付宝'
- column:
name: enabled
valueBoolean: true
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 2
- column:
name: code
value: 'WECHAT'
- column:
name: name
value: '微信支付'
- column:
name: enabled
valueBoolean: true
2. 回滚操作
- changeSet:
id: 5
author: dev_team
changes:
- dropTable:
tableName: temp_data
rollback:
- createTable:
tableName: temp_data
columns:
- column:
name: id
type: int
constraints:
primaryKey: true
3. 上下文控制(环境区分)
- changeSet:
id: 6
author: dev_team
context: dev,test # 仅在dev和test环境执行
changes:
- sql: INSERT INTO config VALUES ('debug_mode','true')
4. 前置条件
- changeSet:
id: 7
author: dev_team
preConditions:
- not:
columnExists:
tableName: user
columnName: age
changes:
- addColumn:
tableName: user
columns:
- column:
name: age
type: int
转换工具:如何将现有数据库转为Liquibase?
方法1:使用generateChangeLog命令
步骤:
- 创建一个空数据库
mysql -u root -p -e "CREATE DATABASE test_db_empty;"
- 导入现有数据库结构
mysqldump -u root -p --no-data existing_db > schema.sql
mysql -u root -p test_db_empty < schema.sql
- 生成变更日志
liquibase --changeLogFile=generated-changelog.xml \
--driver=com.mysql.cj.jdbc.Driver \
--url="jdbc:mysql://localhost:3306/test_db_empty" \
--username=root \
--password=123456 \
generateChangeLog
生成的generated-changelog.xml包含完整的数据库结构,可作为初始版本使用 。
方法2:使用diffChangeLog(推荐)
比较现有数据库与期望状态,仅生成差异变更:
liquibase --changeLogFile=diff-changelog.xml \
--driver=com.mysql.cj.jdbc.Driver \
--url="jdbc:mysql://localhost:3308/db_v1" \
--username=root \
--password=123456 \
--reference-url="jdbc:mysql://localhost:3308/db_v2" \
--reference-username=root \
--reference-password=123456 \
--reference-driver=com.mysql.cj.jdbc.Driver \
diffChangeLog
生成的 diff-changelog.xml,在部署之前,应检查由 diffChangeLog/generateChangeLog 生成的变更日志的正确性和完整性。有些数据库对象及其依赖项无法自动表示,可能需要手动更新以确保部署的准确性。
经过验证,表信息的变更(字段增删改、索引、外键、注释信息)都可以生成变更,这真的是一个极佳的数据库版本差异变更的神器啊
方法3:使用第三方工具
SQLDiff:比较两个数据库结构生成迁移SQL
DBeaver:数据库工具导出变更脚本
注意:生成的变更日志需要人工审核,确保 correctness。
企业级实战:解决常见难题
问题1:多数据库字段类型适配
场景:MySQL的TEXT类型在Oracle中应映射为CLOB,在PostgreSQL中应为TEXT。
解决方案:使用Liquibase的数据库类型映射
databaseChangeLog:
- changeSet:
id: 1
author: dba
changes:
- createTable:
tableName: document
columns:
- column:
name: content
# Liquibase会根据目标数据库自动映射类型
type: LONGTEXT # MySQL: TEXT, Oracle: CLOB, PostgreSQL: TEXT
高级用法:自定义类型映射
// 创建自定义类型映射器
public class CustomTypeMapping implements liquibase.database.type.TypeMapping {
@Override
public String getColumnType(String columnType) {
if ("LONGTEXT".equals(columnType)) {
String database = getDatabase().getDatabaseProductName();
if ("Oracle".equals(database)) {
return "CLOB";
}
}
return columnType;
}
}
问题2:处理大对象(BLOB/CLOB)
场景:需要初始化包含图片、文件等二进制数据、初始化数据比较多时。
解决方案:使用loadData标签
databaseChangeLog:
- changeSet:
id: 7-load-data
author: backend_team
# 将 contexts 属性简化为逗号分隔的字符串
contexts: dev, test, production
comment: 使用loadData加载文件
changes:
- loadData:
tableName: payment_method
columns:
- column:
name: id
type: int
- column:
name: code
- column:
name: name
- column:
name: enabled
index: 4
type: boolean
# 注释开头信息
commentLineStartsWith: "//"
encoding: UTF-8
file: example/payment_method.csv
# 字段分隔符
separator: ","
# 是否用引号引用起来
quotchar: "\""
# 是否使用相对路径
relativeToChangelogFile: true
# 插入参数优化
usePreparedStatements: true
rollback:
- delete:
tableName: payment_method
example/payment_method.csv 文件示例内容
id,code,name,enabled
// 我是文件注释
6,'Paypal6',"贝宝6", t
7,'Paypal7','贝宝7', true
执行结果
注释可以被忽略,
t和true都可以正常转换为实际的格式插入,双引号不会插入,单引号可以插入,指定字段分隔符,如果非标准csv可以指定分隔符

注意事项:
- Liquibase 3.6.2+版本对CLOB处理有改进,如遇问题请升级版本
- 大文件建议使用文件存储,数据库仅存URL
问题3:外键约束管理
场景:添加外键约束时需要确保父表已存在。
解决方案:使用依赖关系或分步执行
databaseChangeLog:
# 先创建父表
- changeSet:
id: 1
author: dev_team
changes:
- createTable:
tableName: user
columns:
- column:
name: id
type: bigint
constraints:
primaryKey: true
# 再创建子表(含外键)
- changeSet:
id: 2
author: dev_team
changes:
- createTable:
tableName: order
columns:
- column:
name: id
type: bigint
constraints:
primaryKey: true
- column:
name: user_id
type: bigint
constraints:
nullable: false
# 外键约束
foreignKeyName: fk_order_user
references:
column: id
table: user
问题4:数据库注释处理
场景:需要为表和字段添加注释(MySQL的COMMENT)。
解决方案:使用remarks属性
databaseChangeLog:
- changeSet:
id: 3
author: dev_team
changes:
- createTable:
tableName: user
remarks: "用户信息表" # 表级注释
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
remarks: "用户主键ID" # 列级注释
- column:
name: username
type: varchar(50)
constraints:
nullable: false
remarks: "用户名,用于登录"
不同数据库的注释支持:
- MySQL:直接使用COMMENT属性
- PostgreSQL:使用COMMENT ON TABLE/COLUMN
- Oracle:使用COMMENT ON TABLE/COLUMN
- SQL Server:使用sp_updateextendedproperty存储过程
Liquibase会根据目标数据库自动生成相应的注释语句,我们无需自行维护不同数据库的sql语句。
问题5:初始化数据管理
场景:系统需要基础配置数据、权限数据等。
解决方案:使用SQL文件或insert标签
方法1:使用SQL文件
databaseChangeLog:
- changeSet:
id: 4
author: dev_team
changes:
- sqlFile:
path: db/changelog/v1.0/init-data.sql
方法2:使用insert标签(适合少量数据)
数据较多时,建议使用xml格式
databaseChangeLog:
- changeSet:
id: 5
author: dev_team
changes:
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 2
- column:
name: code
value: 'WECHAT'
- column:
name: name
value: '微信支付'
- column:
name: enabled
valueBoolean: true
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 3
- column:
name: code
value: 'CARD'
- column:
name: name
value: '银行卡'
- column:
name: enabled
valueBoolean: true
方法3:使用loadData(适合大量数据)
databaseChangeLog:
- changeSet:
id: 6
author: dev_team
changes:
- loadData:
tableName: permission
columns:
- column:
name: id
- column:
name: code
- column:
name: name
file: db/changelog/v1.0/permissions.csv
CSV文件格式:
id,code,name
1,user:view,查看用户
2,user:create,创建用户
3,user:edit,编辑用户
高级技巧:让Liquibase更好用
1. 标签管理(Tagging)
为重要版本打标签,便于回滚:
# 标记当前版本
liquibase tag v1.0.0
# 回滚到指定标签
liquibase rollback v1.0.0
2. 上下文环境隔离
# 仅在生产环境执行
- changeSet:
id: 10
author: dba
context: production
changes:
- sql: "UPDATE config SET value='prod' WHERE key='env'"
# 排除某个环境
- changeSet:
id: 11
author: dev_team
contexts:
- exclude:
- production
changes:
- sql: "INSERT INTO debug_logs VALUES (...)"
3. 变更集分组
使用include文件组织变更:
# 主日志
databaseChangeLog:
- include:
file: db/changelog/tables.yaml
- include:
file: db/changelog/indexes.yaml
- include:
file: db/changelog/data.yaml
4. Maven集成
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>4.27.0</version>
<configuration>
<changeLogFile>db/changelog/master.xml</changeLogFile>
<driver>com.mysql.cj.jdbc.Driver</driver>
<url>jdbc:mysql://localhost:3306/test_db</url>
<username>root</username>
<password>123456</password>
</configuration>
</plugin>
# 执行更新
mvn liquibase:update
# 执行回滚
mvn liquibase:rollback
# 生成变更日志
mvn liquibase:generateChangeLog
5. CI/CD集成
Jenkins Pipeline示例:
pipeline {
stages {
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('DB Migration') {
steps {
sh 'mvn liquibase:update'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Deploy') {
steps {
sh 'mvn package'
// 部署到生产环境
}
}
}
}
信创数据库支持
目前 Liquibase 官方暂不直接支持达梦、人大金仓等信创数据库,但社区提供了成熟的 第三方适配方案和 db-migration 扩展项目。通过这些方案,可以实现对这些国产数据库的版本控制,核心思路是利用适配层转接标准 JDBC 协议。
db-migration 开源项目
Flyway、Liquibase 扩展支持达梦(DM)、南大通用(GBase 8s)、OpenGauss 等国产数据库。
Github地址:https://github.com/mengweijin/db-migration
优点:springboot项目 拿来即用
缺点:仅做了简单实现,适配不一定完全,采用源码覆盖方式,未使用官方推荐方式,下载jar包无法使用命令行方式进行适配
自定义扩展
Liquibase的代码提供了成熟的 SPI 扩展方式,可以自定义实现。
这里我提供一个优化后的 达梦适配版本(命令行、springboot项目):
适配包下载:https://pan.alianga.com/s/3ycz
- 把
liquibase-dm-1.0.0.jar文件放到 liquibase的 lib目录下 - 把达梦的 JDBC 驱动包,也放到 liquibase 的 lib目录
liquibase
lib
├── dm-jdbc8-8.1.2.192.jar
├── gsjdbc4-GaussDB-Kernel-505-5.0.0.4.2.jar
├── liquibase_autocomplete_mac.bash
├── liquibase_autocomplete.sh
├── liquibase_autocomplete.zsh
├── liquibase-dm-1.0.0.jar
├── mysql-connector-j-9.5.0.jar
├── ojdbc8-19.3.0.0.jar
└── README.txt
- 执行示例
liquibase update --changeLogFile=master.yaml --driver=dm.jdbc.driver.DmDriver --url="jdbc:dm://127.0.0.1:5236" --username=TEST_DB --password=TEST_DB --log-level=debug
最佳实践:避免这些坑!
推荐做法
- 版本号规范:采用语义化版本(v1.0.1),每次变更递增
- 变更集原子性:每个变更集只做一件事,便于回滚
- 避免DROP操作:优先使用ALTER修改,而非删除重建
- 开发环境启用:
spring.liquibase.enabled=true,快速迭代 - 生产环境验证:变更前在预生产环境测试
- 定期清理:归档旧变更日志,保持changelog清洁
避免做法
- 不要手动修改数据库:绕过Liquibase直接操作数据库
- 不要重复执行变更集:会导致报错和数据不一致
- 不要使用DROP CASCADE:可能导致数据丢失
- 不要忽略回滚脚本:变更前必须确认可回滚性
- 不要在生产环境调试:先用dev/test环境验证
常见错误及解决方案
错误1:ChangeSet already executed
ERROR: ChangeSet classpath:/db/changelog/v1.0/changelog-v1.0.yaml::1::dev_team has already been executed
解决:检查变更集ID和author是否唯一,或使用liquibase clearCheckSums清理(谨慎使用)
错误2:Could not find databaseChangeLog node
ERROR: Could not find databaseChangeLog node
解决:检查YAML文件格式是否正确,确保根元素为databaseChangeLog
错误3:Databasechangelog already exists
ERROR: relation databasechangelog already exists
解决:数据库已存在旧版本Liquibase表,需手动清理或升级数据库
性能优化:让迁移更快更稳
1. 批量执行
# 不好:多个变更集
- changeSet:
id: 1
changes:
- addColumn: ...
- changeSet:
id: 2
changes:
- addColumn: ...
# 推荐:单个变更集多列
- changeSet:
id: 1
changes:
- addColumn:
tableName: user
columns:
- column:
name: email
type: varchar(100)
- column:
name: phone
type: varchar(20)
2. 索引延迟创建
# 先建表
- changeSet:
id: 1
author: dev_team
changes:
- createTable:
tableName: order
columns:
- column:
name: id
type: bigint
constraints:
primaryKey: true
# 后建索引(表数据量大时更高效)
- changeSet:
id: 2
author: dev_team
changes:
- createIndex:
tableName: order
indexName: idx_order_user
columns:
- column:
name: user_id
3. 使用SQL文件优化复杂脚本
- changeSet:
id: 3
author: dev_team
changes:
- sqlFile:
path: db/changelog/v1.0/complex_migration.sql
# splitStatements: true # 自动分割多条SQL
# stripComments: true # 去除注释
4. 监控和日志
# 启用详细日志
logging:
level:
liquibase: INFO
liquibase.changelog: DEBUG
实际案例:电商订单系统实战
需求场景
某电商平台订单系统需要:
- 支持MySQL和Oracle双数据库
- 用户表、订单表、订单详情表
- 订单表需添加大字段(商品图片URL)
- 初始化支付方式配置数据
- 支持回滚到上一版本
完整变更日志
master.yaml:
databaseChangeLog:
- include:
file: db/changelog/tables.yaml
- include:
file: db/changelog/data.yaml
tables.yaml:
databaseChangeLog:
- changeSet:
id: 1
author: backend_team
changes:
- createTable:
tableName: user
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: username
type: varchar(50)
constraints:
nullable: false
- column:
name: email
type: varchar(100)
constraints:
nullable: false
remarks: "用户邮箱"
- column:
name: created_at
type: datetime
constraints:
nullable: false
defaultValueComputed: CURRENT_TIMESTAMP
rollback:
- dropTable:
tableName: user
- changeSet:
id: 2
author: backend_team
changes:
- createTable:
tableName: order
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: user_id
type: bigint
constraints:
nullable: false
remarks: "下单用户ID"
- column:
name: order_no
type: varchar(50)
constraints:
nullable: false
unique: true # <-- 移动到 constraints 节点内部
- column:
name: total_amount
type: decimal(10,2)
constraints:
nullable: false
- column:
name: status
type: varchar(20)
constraints:
nullable: false
defaultValue: 'PENDING'
- column:
name: created_at
type: datetime
constraints:
nullable: false
defaultValueComputed: CURRENT_TIMESTAMP
- column:
name: updated_at
type: datetime
constraints:
nullable: false
defaultValueComputed: CURRENT_TIMESTAMP
remarks: "订单表"
rollback:
- dropTable:
tableName: order
- changeSet:
id: 3
author: backend_team
changes:
- addColumn:
tableName: order
columns:
- column:
name: product_image
type: longtext
constraints:
nullable: true
remarks: "商品图片URL(支持多个图片,逗号分隔)"
rollback:
- dropColumn:
tableName: order
columnName: product_image
- changeSet:
id: 4
author: backend_team
changes:
- createIndex:
tableName: order
indexName: idx_order_user
columns:
- column:
name: user_id
- createIndex:
tableName: order
indexName: idx_order_created
columns:
- column:
name: created_at
rollback:
- dropIndex:
tableName: order
indexName: idx_order_user
- dropIndex:
tableName: order
indexName: idx_order_created
- changeSet:
id: add-payment_method
author: backend_team
changes:
- createTable:
tableName: payment_method
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: code
type: varchar(50)
constraints:
nullable: false
- column:
name: name
type: varchar(100)
constraints:
nullable: false
remarks: "用户邮箱"
- column:
name: created_at
type: datetime
constraints:
nullable: false
defaultValueComputed: CURRENT_TIMESTAMP
rollback:
- dropTable:
tableName: payment_method
- changeSet:
id: add-payment_method-column-enabled
author: backend_team
changes:
- addColumn:
tableName: payment_method
columns:
- column:
name: enabled
type: int(1)
constraints:
nullable: false
defaultValue: 1
rollback:
- dropColumn:
tableName: payment_method
columnName: enabled
data.yaml:
databaseChangeLog:
- changeSet:
id: 5
author: backend_team
# 将 contexts 属性简化为逗号分隔的字符串
contexts: dev, test, production
changes:
# 将多行数据拆分为多个单独的 insert change
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 1
- column:
name: code
value: 'ALIPAY'
- column:
name: name
value: '支付宝'
- column:
name: enabled
valueBoolean: true
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 2
- column:
name: code
value: 'WECHAT'
- column:
name: name
value: '微信支付'
- column:
name: enabled
valueBoolean: true
- insert:
tableName: payment_method
columns:
- column:
name: id
value: 3
- column:
name: code
value: 'CARD'
- column:
name: name
value: '银行卡'
- column:
name: enabled
valueBoolean: true
rollback:
- delete:
tableName: payment_method
where: "id IN (1,2,3)"
- changeSet:
id: 6-insert-sql
author: backend_team
# 将 contexts 属性简化为逗号分隔的字符串
contexts: dev, test, production
changes:
# 将多行数据拆分为多个单独的 insert change
- sql: INSERT INTO payment_method (id,code,name,enabled) VALUES (5,'Paypal','贝宝', true)
rollback:
- delete:
tableName: payment_method
where: "id IN (5)"
- changeSet:
id: 7-load-data
author: backend_team
# 将 contexts 属性简化为逗号分隔的字符串
contexts: dev, test, production
comment: 使用loadData加载文件
changes:
- loadData:
tableName: payment_method
columns:
- column:
name: id
type: int
- column:
name: code
- column:
name: name
- column:
name: enabled
index: 4
type: boolean
# 注释开头信息
commentLineStartsWith: "//"
encoding: UTF-8
file: example/payment_method.csv
# 字段分隔符
separator: ","
# 是否用引号引用起来
quotchar: "\""
# 是否使用相对路径
relativeToChangelogFile: true
# 插入参数优化
usePreparedStatements: true
rollback:
- delete:
tableName: payment_method
where: "id IN (6,7)"
使用步骤
可先使用 update-sql 查看要执行的 sql 脚本,也可验证写的 yaml或xml等规则是否正确
liquibase update-sql --changeLogFile=master.yaml \
--driver=com.mysql.cj.jdbc.Driver \
--url="jdbc:mysql://localhost:3308/schedule_develop" \
--username=root \
--password=123456
则会有类似如下输出,可以根据输出的错误或 sql语句调整规则文件,以确保准确性和完整性
####################################################
## _ _ _ _ ##
## | | (_) (_) | ##
## | | _ __ _ _ _ _| |__ __ _ ___ ___ ##
## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ ##
## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ ##
## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| ##
## | | ##
## |_| ##
## ##
## Get documentation at docs.liquibase.com ##
## Get certified courses at learn.liquibase.com ##
## ##
####################################################
Starting Liquibase at 15:00:24 using Java 21.0.8 (version 5.0.1 #9400 built at 2025-10-03 17:37+0000)
Liquibase Version: 5.0.1
WARNING:
Liquibase detected the following invalid Community LIQUIBASE_* environment variables:
- LIQUIBASE_PATH
Find the list of valid environment variables at https://docs.liquibase.com/environment-variables
-- Create Database Lock Table
CREATE TABLE schedule_develop.databasechangeloglock (ID INT NOT NULL, `LOCKED` TINYINT NOT NULL, LOCKGRANTED datetime NULL, LOCKEDBY VARCHAR(255) NULL, CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID));
-- Initialize Database Lock Table
DELETE FROM schedule_develop.databasechangeloglock;
INSERT INTO schedule_develop.databasechangeloglock (ID, `LOCKED`) VALUES (1, 0);
-- Lock Database
UPDATE schedule_develop.databasechangeloglock SET `LOCKED` = 1, LOCKEDBY = 'zml (172.20.0.1)', LOCKGRANTED = NOW() WHERE ID = 1 AND `LOCKED` = 0;
-- Create Database Change Log Table
CREATE TABLE schedule_develop.databasechangelog (ID VARCHAR(255) NOT NULL, AUTHOR VARCHAR(255) NOT NULL, FILENAME VARCHAR(255) NOT NULL, DATEEXECUTED datetime NOT NULL, ORDEREXECUTED INT NOT NULL, EXECTYPE VARCHAR(10) NOT NULL, MD5SUM VARCHAR(35) NULL, `DESCRIPTION` VARCHAR(255) NULL, COMMENTS VARCHAR(255) NULL, TAG VARCHAR(255) NULL, LIQUIBASE VARCHAR(20) NULL, CONTEXTS VARCHAR(255) NULL, LABELS VARCHAR(255) NULL, DEPLOYMENT_ID VARCHAR(10) NULL);
-- *********************************************************************
-- Update Database Script
-- *********************************************************************
-- Change Log: master.yaml
-- Ran at: 2025/12/10 15:00
-- Against: root@172.20.0.1@jdbc:mysql://localhost:3308/schedule_develop
-- Liquibase version: 5.0.1
-- *********************************************************************
-- Changeset db/changelog/tables.yaml::1::backend_team
CREATE TABLE schedule_develop.user (id BIGINT AUTO_INCREMENT NOT NULL, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, created_at datetime DEFAULT 'CURRENT_TIMESTAMP' NOT NULL, CONSTRAINT PK_USER PRIMARY KEY (id));
INSERT INTO schedule_develop.databasechangelog (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('1', 'backend_team', 'db/changelog/tables.yaml', NOW(), 1, '9:473199fafaa63fd7cb06368dcfb88273', 'createTable tableName=user', '', 'EXECUTED', NULL, NULL, '5.0.1', '5350023913');
-- Changeset db/changelog/tables.yaml::2::backend_team
CREATE TABLE schedule_develop.`order` (id BIGINT AUTO_INCREMENT NOT NULL, user_id BIGINT NOT NULL COMMENT '下单用户ID', order_no VARCHAR(50) NOT NULL, total_amount DECIMAL(10, 2) NOT NULL, status VARCHAR(20) DEFAULT 'PENDING' NOT NULL, created_at datetime DEFAULT 'CURRENT_TIMESTAMP' NOT NULL, updated_at datetime DEFAULT 'CURRENT_TIMESTAMP' NOT NULL, CONSTRAINT PK_ORDER PRIMARY KEY (id), UNIQUE (order_no)) COMMENT='订单表';
INSERT INTO schedule_develop.databasechangelog (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('2', 'backend_team', 'db/changelog/tables.yaml', NOW(), 2, '9:17792f8514bf1c660310075d9899ca86', 'createTable tableName=order', '', 'EXECUTED', NULL, NULL, '5.0.1', '5350023913');
-- Changeset db/changelog/tables.yaml::3::backend_team
ALTER TABLE schedule_develop.`order` ADD product_image LONGTEXT NULL COMMENT '商品图片URL(支持多个图片,逗号分隔)';
INSERT INTO schedule_develop.databasechangelog (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('3', 'backend_team', 'db/changelog/tables.yaml', NOW(), 3, '9:f6588d2e7fc6e251dcd9508403663d77', 'addColumn tableName=order', '', 'EXECUTED', NULL, NULL, '5.0.1', '5350023913');
-- Changeset db/changelog/tables.yaml::4::backend_team
CREATE INDEX idx_order_user ON schedule_develop.`order`(user_id);
CREATE INDEX idx_order_created ON schedule_develop.`order`(created_at);
INSERT INTO schedule_develop.databasechangelog (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('4', 'backend_team', 'db/changelog/tables.yaml', NOW(), 4, '9:007ae082c863fc53491754bd0fd72084', 'createIndex indexName=idx_order_user, tableName=order; createIndex indexName=idx_order_created, tableName=order', '', 'EXECUTED', NULL, NULL, '5.0.1', '5350023913');
-- Changeset db/changelog/data.yaml::5::backend_team
INSERT INTO schedule_develop.payment_method (id, code, name, enabled) VALUES ('1', 'ALIPAY', '支付宝', 1);
INSERT INTO schedule_develop.payment_method (id, code, name, enabled) VALUES ('2', 'WECHAT', '微信支付', 1);
INSERT INTO schedule_develop.payment_method (id, code, name, enabled) VALUES ('3', 'CARD', '银行卡', 1);
INSERT INTO schedule_develop.databasechangelog (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('5', 'backend_team', 'db/changelog/data.yaml', NOW(), 5, '9:e871bc39d1a40a3a5af7f7868edddde7', 'insert tableName=payment_method; insert tableName=payment_method; insert tableName=payment_method', '', 'EXECUTED', NULL, NULL, '5.0.1', '5350023913');
-- Release Database Lock
UPDATE schedule_develop.databasechangeloglock SET `LOCKED` = 0, LOCKEDBY = NULL, LOCKGRANTED = NULL WHERE ID = 1;
Liquibase command 'update-sql' was executed successfully.
确保无误后,则可以通过 update 直接执行
liquibase update --changeLogFile=master.yaml \
--driver=com.mysql.cj.jdbc.Driver \
--url="jdbc:mysql://localhost:3308/schedule_develop" \
--username=root \
--password=mingliang
- 开发环境:
mvn spring-boot:run
# Liquibase自动创建表结构
- 测试环境:
mvn clean package
java -jar order-system.jar
# 应用自动更新数据库结构
- 生产环境:
# 备份数据库
mysqldump -u root -p order_db > backup_$(date +%Y%m%d).sql
# 执行迁移
java -jar order-system.jar
# 或使用命令行
liquibase --changeLogFile=master.yaml update
# 验证
mysql -u root -p order_db -e "SHOW TABLES;"
- 回滚示例(如果发现product_image字段有问题):
liquibase需要补充 --url 等参数,这里只示例回滚参数
# 回滚到上一版本
liquibase rollbackCount --rollbackCount=1
# 或回滚到指定版本
liquibase rollback v1.0.0
# 按日期回滚,回滚在指定日期和时间之后应用的所有变更集(包含指定的时间)。
liquibase rollbackToDate --date="2025-12-13 21:52:58"
安全预览:回滚 SQL
在执行任何实际的回滚操作之前,强烈建议先预览将要执行的原始 SQL 语句。这些预览命令不会修改您的数据库。
- 预览按标签回滚的 SQL:
rollbackSql --rollbackTag=... - 预览按数量回滚的 SQL:
rollbackCount-sql --rollbackCount=... - 预览按日期回滚的 SQL:
rollbackToDateSql --rollbackDate=...
结语
参考内容:
- 官方文档:https://docs.liquibase.com/
- GitHub仓库:https://github.com/liquibase/liquibase
- 社区论坛:https://forum.liquibase.org/
如果这篇文章对你有帮助,请点赞、收藏、转发三连~
Q.E.D.


