news 2026/7/1 15:54:43

Liquibase 入门指南:数据库版本控制的最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Liquibase 入门指南:数据库版本控制的最佳实践

一、什么是 Liquibase?

Liquibase是一个开源的数据库 schema 变更管理工具,由 Nathan Voxland 于 2006 年创建。它的核心思想是:像管理代码一样管理数据库结构变更

你不再需要手动在开发、测试、生产环境分别执行 SQL 脚本,也不需要在团队中靠口头传递alter table语句。Liquibase 通过changelog 文件(变更日志)来记录、版本化、追踪所有数据库变更,并自动应用到目标数据库。

核心特性

特性说明
版本控制每次数据库变更都是一个 changeset,被唯一标识并追踪
多数据库支持同一份 changelog 可部署到 MySQL、PostgreSQL、Oracle、SQL Server、H2 等 20+ 数据库
四种 changelog 格式SQL / XML / YAML / JSON,团队可选自己最熟悉的格式
自动追踪在数据库中自动创建DATABASECHANGELOGDATABASECHANGELOGLOCK
回滚能力支持按 tag、按数量、按时间回滚变更
CI/CD 集成Maven、Gradle、Spring Boot、Jenkins、GitHub Actions 等无缝集成

二、Liquibase 工作原理

Liquibase 的工作流程非常简单:

编写 changelog → 运行 liquibase update → Liquibase 自动对比 → 只执行未部署的变更

当首次执行update时,Liquibase 会在数据库中自动创建两张跟踪表:

  1. DATABASECHANGELOG— 记录所有已执行的 changeset,包括文件名、作者、ID、MD5 校验和、执行时间、部署 ID 等

  2. DATABASECHANGELOGLOCK— 分布式锁,防止多个 Liquibase 实例同时修改数据库

每次执行时,Liquibase 会比较 changelog 中的 changeset 与DATABASECHANGELOG表中的记录,只执行那些尚未部署的新 changeset,已经执行过的不会重复运行。


三、Changelog 与 Changeset 详解

3.1 基本概念

  • Changelog:一个文本文件,按顺序列出所有数据库变更

  • Changeset:变更的最小单元,由id+author唯一标识

3.2 四种格式对比

① SQL 格式(推荐 DBA 使用)

--liquibase formatted sql ​ --changeset nvoxland:1 CREATE TABLE person ( id INT PRIMARY KEY, name VARCHAR(255) ); --rollback drop table person; ​ --changeset nvoxland:2 ALTER TABLE person ADD COLUMN email VARCHAR(255);

格式特点:直接写 SQL,控制力最强,但数据库不通用 适用场景:DBA 团队、需要精确控制 SQL 的场景 自动回滚:不支持,需手动写 rollback 语句

② XML 格式(最传统、功能最全)

<?xml version="1.1" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> ​ <changeSet id="1" author="nvoxland"> <createTable tableName="person"> <column name="id" type="int" autoIncrement="true"> <constraints primaryKey="true" nullable="false"/> </column> <column name="name" type="varchar(50)"/> </createTable> </changeSet> ​ <changeSet id="2" author="nvoxland"> <addColumn tableName="person"> <column name="email" type="varchar(255)"/> </addColumn> </changeSet> </databaseChangeLog>

格式特点:声明式,Liquibase 自动生成目标数据库的 SQL 适用场景:Java 生态项目、需要跨数据库支持 自动回滚:多数 Change Type 支持自动回滚

③ YAML 格式(最简洁)

databaseChangeLog: - changeSet: id: 1 author: nvoxland changes: - createTable: tableName: person columns: - column: name: id type: int autoIncrement: true constraints: primaryKey: true nullable: false - column: name: name type: varchar(50) - column: name: email type: varchar(255)

格式特点:简洁易读,YAML 本身就适合做配置 适用场景:DevOps 团队、配置驱动型项目 自动回滚:支持

④ JSON 格式

{ "databaseChangeLog": [ { "changeSet": { "id": "1", "author": "nvoxland", "changes": [ { "createTable": { "tableName": "person", "columns": [ { "column": { "name": "id", "type": "int", "autoIncrement": true, "constraints": { "primaryKey": true, "nullable": false } } }, { "column": { "name": "name", "type": "varchar(50)" } }, { "column": { "name": "email", "type": "varchar(255)" } } ] } } ] } } ] }

格式特点:前端/JS 开发者熟悉 适用场景:Node.js / TypeScript 项目 自动回滚:支持

小技巧:四种格式可以混用!根 changelog 用 XML,通过<include>引入 SQL 或 YAML 子文件。

3.3 Changeset 常用属性

属性作用
id+author必填,联合唯一标识一个 changeset
dbms指定目标数据库类型,如dbms:mysql
context按上下文过滤,如context:prod
labels按标签过滤,比 context 更灵活
runAlways每次执行都运行(即使已部署过)
runOnChange当 changeset 内容变化时重新运行
runInTransaction是否在事务中执行(默认 true)
failOnError出错时是否中止(默认 true)

四、快速上手

4.1 安装

方式一:下载二进制(推荐)

从 liquibase.org/download 下载,解压即用:

# 添加 liquibase 到 PATH export PATH=$PATH:/path/to/liquibase ​ # 验证安装 liquibase --version

方式二:Homebrew(macOS)

brew install liquibase

方式三:Docker

docker run --rm -v $(pwd)/changelog:/liquibase/changelog liquibase/liquibase:latest update

4.2 初始化项目

# 创建项目目录 mkdir my-liquibase-project && cd my-liquibase-project ​ # 初始化项目(生成示例结构和配置文件) liquibase init project

这会生成一个liquibase.properties配置文件:

# 数据库连接信息 changeLogFile=changelog/root.changelog.xml url=jdbc:mysql://localhost:3306/mydb username=root password=mysecret driver=com.mysql.cj.jdbc.Driver ​ # 其他配置 liquibase.hub.mode=off

4.3 编写第一个 changelog

changelog/目录下创建root.changelog.xml

<?xml version="1.1" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd"> ​ <changeSet id="1" author="zhangsan"> <createTable tableName="user"> <column name="id" type="bigint" autoIncrement="true"> <constraints primaryKey="true" nullable="false"/> </column> <column name="username" type="varchar(50)"> <constraints nullable="false" unique="true"/> </column> <column name="password_hash" type="varchar(255)"> <constraints nullable="false"/> </column> <column name="created_at" type="timestamp"> <constraints nullable="false"/> </column> </createTable> </changeSet> ​ <changeSet id="2" author="zhangsan"> <createTable tableName="order"> <column name="id" type="bigint" autoIncrement="true"> <constraints primaryKey="true" nullable="false"/> </column> <column name="user_id" type="bigint"> <constraints nullable="false"/> </column> <column name="amount" type="decimal(10,2)"/> <column name="status" type="varchar(20)" defaultValue="PENDING"/> </createTable> <addForeignKeyConstraint constraintName="fk_order_user" baseTableName="order" baseColumnNames="user_id" referencedTableName="user" referencedColumnNames="id"/> </changeSet> </databaseChangeLog>

4.4 执行部署

# 查看待部署的变更 liquibase status --verbose ​ # 预览即将执行的 SQL(不真正执行) liquibase update-sql ​ # 执行部署 liquibase update ​ # 查看部署历史 liquibase history

五、常用命令清单

部署类

命令说明
update部署所有未执行的 changeset
update-sql预览 update 的 SQL(不执行)
update-count <N>只部署接下来的 N 个 changeset
update-to-tag <tag>部署到指定 tag 为止
update-testing-rollback部署 → 回滚 → 重新部署(验证回滚逻辑)

回滚类

命令说明
rollback <tag>回滚到指定 tag
rollback-to-date <date>回滚到指定时间点
rollback-count <N>回滚最近 N 个 changeset
future-rollback-sql预览未来变更的回滚 SQL

对比与快照

命令说明
diff比较两个数据库的差异
diff-changelog从差异生成新的 changelog 文件
snapshot捕获当前数据库 schema 快照
generate-changelog从已有数据库反向生成 changelog

状态与工具

命令说明
status查看待部署 changeset 数量
history查看部署历史
validate校验 changelog 语法
tag <name>在当前数据库状态打 tag
release-locks释放死锁(分布式锁意外残留时)
clear-checksums清除校验和(changeset 内容变更后使用)

六、Spring Boot 集成

Liquibase 与 Spring Boot 的集成是开箱即用的——加一个依赖就够了。

6.1 添加依赖

Maven:

<dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>4.31.1</version> </dependency>

Gradle:

implementation 'org.liquibase:liquibase-core:4.31.1'

6.2 配置

# application.yml spring: liquibase: enabled: true change-log: classpath:db/changelog/root.changelog.xml datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: secret

6.3 放置 changelog 文件

src/main/resources/db/changelog/ ├── root.changelog.xml ├── v1.0/ │ ├── init-schema.xml │ └── init-data.sql └── v1.1/ └── add-order-table.yaml

根 changelog 通过<include>引入子文件:

<databaseChangeLog ...> <include file="db/changelog/v1.0/init-schema.xml"/> <include file="db/changelog/v1.0/init-data.sql"/> <include file="db/changelog/v1.1/add-order-table.yaml"/> </databaseChangeLog>

Spring Boot 启动时自动执行liquibase update,无需任何额外代码。


七、多环境管理

7.1 使用 Context(推荐)

在 changeset 上标记环境:

<changeSet id="1" author="zhangsan" context="dev,test"> <!-- 只在 dev 和 test 环境执行的变更 --> <insert tableName="user"> <column name="username" value="admin"/> <column name="password_hash" value="xxx"/> </insert> </changeSet> ​ <changeSet id="2" author="zhangsan" context="prod"> <!-- 生产环境专用变更 --> <createIndex tableName="order" indexName="idx_order_status"> <column name="status"/> </createIndex> </changeSet>

执行时指定 context:

liquibase --contexts=prod update

7.2 使用 Preconditions

在执行前校验条件:

<changeSet id="1" author="zhangsan"> <preConditions onFail="HALT"> <runningAs username="liquibase"/> <tableExists tableName="user"/> </preConditions> <addColumn tableName="user"> <column name="phone" type="varchar(20)"/> </addColumn> </changeSet>

常用 precondition:tableExistscolumnExistssqlCheckdbmsrunningAs等。


八、Liquibase 为什么比手写 SQL 脚本方便?

场景手写 SQL 脚本Liquibase
团队协作谁改了啥全靠自觉,容易漏执行自动追踪,changelog 全在 Git 里
多环境执行手动记录哪个脚本在哪执行过自动对比DATABASECHANGELOG,只跑新的
回滚基本没有回滚,或靠备份恢复支持按 tag/时间/数量回滚
幂等性重复执行会报错("表已存在")已执行的自动跳过,不会报错
跨数据库迁移MySQL 脚本在 Oracle 上不能用声明式 changelog 自动生成目标数据库的 SQL
CI/CD 集成需要自己写脚本编排Maven/Gradle/Docker 开箱即用
变更历史靠聊天记录和邮件DATABASECHANGELOG表就是完整的变更审计日志

九、最佳实践

  1. 一个 changeset 只做一件事— 便于回滚和排查问题

  2. 永远不要修改已部署的 changeset— 创建新的 changeset 来变更。如果必须修改已部署的,使用runOnChange属性

  3. changelog 文件放到 Git 里— 像源代码一样管理,PR review 时可以审查数据库变更

  4. 使用 tag 标记版本— 每次发版前打 tag,方便回滚到特定版本

  5. update-sqlupdate— 生产环境执行前先预览 SQL

  6. 回滚逻辑一定要写— SQL 格式的手动写--rollback,声明式格式尽量选支持自动回滚的 Change Type

  7. 按版本目录组织 changelog— 如v1.0/v1.1/v2.0/


十、总结

Liquibase 是 Java 生态中最成熟的数据库版本控制工具(没有之一)。它让数据库变更变得:

  • 可追踪— 每一次变更都有记录

  • 可重复— 任何环境跑一次就能复现

  • 可回滚— 出问题能快速恢复

  • 可协作— 团队通过 Git + PR 管理数据库变更

不管你是刚起步的个人项目,还是多人协作的企业级应用,Liquibase 都能让你的数据库管理更规范、更安全。


参考资源:

  • Liquibase 官方文档

  • Liquibase GitHub

  • 官方 Implementation Guide

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 15:51:46

Figma到Unity导入器:5分钟将设计稿变成游戏UI

Figma到Unity导入器&#xff1a;5分钟将设计稿变成游戏UI 【免费下载链接】FigmaToUnityImporter The project that imports nodes from Figma into unity. 项目地址: https://gitcode.com/gh_mirrors/fi/FigmaToUnityImporter 还在为游戏UI开发而头疼吗&#xff1f;Fig…

作者头像 李华
网站建设 2026/7/1 15:47:54

储能BMS微控制器选型难题怎么破:2026五大主流方案专业解析

引言储能电池管理系统&#xff08;BMS&#xff09;是储能系统的核心控制单元&#xff0c;负责电池状态监测、安全保护、均衡管理和通信调度等关键功能。微控制器&#xff08;MCU&#xff09;作为BMS主控芯片&#xff0c;其性能直接决定了系统响应速度、估算精度和运行可靠性。随…

作者头像 李华
网站建设 2026/7/1 15:47:29

【计算机毕业设计案例】基于 SpringBoot 的研究生双选流程管控系统的设计与实现 基于 SpringBoot 的师生选聘信息管理发布系统(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/1 15:41:48

解放双手的革命性方案:MAA明日方舟智能自动化助手深度解析

解放双手的革命性方案&#xff1a;MAA明日方舟智能自动化助手深度解析 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手&#xff0c;全日常一键长草&#xff01;| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https:/…

作者头像 李华