一、什么是 LiquibaseLiquibase是一个开源的数据库 schema 变更管理工具由 Nathan Voxland 于 2006 年创建。它的核心思想是像管理代码一样管理数据库结构变更。你不再需要手动在开发、测试、生产环境分别执行 SQL 脚本也不需要在团队中靠口头传递alter table语句。Liquibase 通过changelog 文件变更日志来记录、版本化、追踪所有数据库变更并自动应用到目标数据库。核心特性特性说明版本控制每次数据库变更都是一个 changeset被唯一标识并追踪多数据库支持同一份 changelog 可部署到 MySQL、PostgreSQL、Oracle、SQL Server、H2 等 20 数据库四种 changelog 格式SQL / XML / YAML / JSON团队可选自己最熟悉的格式自动追踪在数据库中自动创建DATABASECHANGELOG和DATABASECHANGELOGLOCK表回滚能力支持按 tag、按数量、按时间回滚变更CI/CD 集成Maven、Gradle、Spring Boot、Jenkins、GitHub Actions 等无缝集成二、Liquibase 工作原理Liquibase 的工作流程非常简单编写 changelog → 运行 liquibase update → Liquibase 自动对比 → 只执行未部署的变更当首次执行update时Liquibase 会在数据库中自动创建两张跟踪表DATABASECHANGELOG— 记录所有已执行的 changeset包括文件名、作者、ID、MD5 校验和、执行时间、部署 ID 等DATABASECHANGELOGLOCK— 分布式锁防止多个 Liquibase 实例同时修改数据库每次执行时Liquibase 会比较 changelog 中的 changeset 与DATABASECHANGELOG表中的记录只执行那些尚未部署的新 changeset已经执行过的不会重复运行。三、Changelog 与 Changeset 详解3.1 基本概念Changelog一个文本文件按顺序列出所有数据库变更Changeset变更的最小单元由idauthor唯一标识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 version1.1 encodingUTF-8? databaseChangeLog xmlnshttp://www.liquibase.org/xml/ns/dbchangelog xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd ​ changeSet id1 authornvoxland createTable tableNameperson column nameid typeint autoIncrementtrue constraints primaryKeytrue nullablefalse/ /column column namename typevarchar(50)/ /createTable /changeSet ​ changeSet id2 authornvoxland addColumn tableNameperson column nameemail typevarchar(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 常用属性属性作用idauthor必填联合唯一标识一个 changesetdbms指定目标数据库类型如dbms:mysqlcontext按上下文过滤如context:prodlabels按标签过滤比 context 更灵活runAlways每次执行都运行即使已部署过runOnChange当 changeset 内容变化时重新运行runInTransaction是否在事务中执行默认 truefailOnError出错时是否中止默认 true四、快速上手4.1 安装方式一下载二进制推荐从 liquibase.org/download 下载解压即用# 添加 liquibase 到 PATH export PATH$PATH:/path/to/liquibase ​ # 验证安装 liquibase --version方式二HomebrewmacOSbrew install liquibase方式三Dockerdocker run --rm -v $(pwd)/changelog:/liquibase/changelog liquibase/liquibase:latest update4.2 初始化项目# 创建项目目录 mkdir my-liquibase-project cd my-liquibase-project ​ # 初始化项目生成示例结构和配置文件 liquibase init project这会生成一个liquibase.properties配置文件# 数据库连接信息 changeLogFilechangelog/root.changelog.xml urljdbc:mysql://localhost:3306/mydb usernameroot passwordmysecret drivercom.mysql.cj.jdbc.Driver ​ # 其他配置 liquibase.hub.modeoff4.3 编写第一个 changelog在changelog/目录下创建root.changelog.xml?xml version1.1 encodingUTF-8? databaseChangeLog xmlnshttp://www.liquibase.org/xml/ns/dbchangelog xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd ​ changeSet id1 authorzhangsan createTable tableNameuser column nameid typebigint autoIncrementtrue constraints primaryKeytrue nullablefalse/ /column column nameusername typevarchar(50) constraints nullablefalse uniquetrue/ /column column namepassword_hash typevarchar(255) constraints nullablefalse/ /column column namecreated_at typetimestamp constraints nullablefalse/ /column /createTable /changeSet ​ changeSet id2 authorzhangsan createTable tableNameorder column nameid typebigint autoIncrementtrue constraints primaryKeytrue nullablefalse/ /column column nameuser_id typebigint constraints nullablefalse/ /column column nameamount typedecimal(10,2)/ column namestatus typevarchar(20) defaultValuePENDING/ /createTable addForeignKeyConstraint constraintNamefk_order_user baseTableNameorder baseColumnNamesuser_id referencedTableNameuser referencedColumnNamesid/ /changeSet /databaseChangeLog4.4 执行部署# 查看待部署的变更 liquibase status --verbose ​ # 预览即将执行的 SQL不真正执行 liquibase update-sql ​ # 执行部署 liquibase update ​ # 查看部署历史 liquibase history五、常用命令清单部署类命令说明update部署所有未执行的 changesetupdate-sql预览 update 的 SQL不执行update-count N只部署接下来的 N 个 changesetupdate-to-tag tag部署到指定 tag 为止update-testing-rollback部署 → 回滚 → 重新部署验证回滚逻辑回滚类命令说明rollback tag回滚到指定 tagrollback-to-date date回滚到指定时间点rollback-count N回滚最近 N 个 changesetfuture-rollback-sql预览未来变更的回滚 SQL对比与快照命令说明diff比较两个数据库的差异diff-changelog从差异生成新的 changelog 文件snapshot捕获当前数据库 schema 快照generate-changelog从已有数据库反向生成 changelog状态与工具命令说明status查看待部署 changeset 数量history查看部署历史validate校验 changelog 语法tag name在当前数据库状态打 tagrelease-locks释放死锁分布式锁意外残留时clear-checksums清除校验和changeset 内容变更后使用六、Spring Boot 集成Liquibase 与 Spring Boot 的集成是开箱即用的——加一个依赖就够了。6.1 添加依赖Mavendependency groupIdorg.liquibase/groupId artifactIdliquibase-core/artifactId version4.31.1/version /dependencyGradleimplementation org.liquibase:liquibase-core:4.31.16.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: secret6.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 filedb/changelog/v1.0/init-schema.xml/ include filedb/changelog/v1.0/init-data.sql/ include filedb/changelog/v1.1/add-order-table.yaml/ /databaseChangeLogSpring Boot 启动时自动执行liquibase update无需任何额外代码。七、多环境管理7.1 使用 Context推荐在 changeset 上标记环境changeSet id1 authorzhangsan contextdev,test !-- 只在 dev 和 test 环境执行的变更 -- insert tableNameuser column nameusername valueadmin/ column namepassword_hash valuexxx/ /insert /changeSet ​ changeSet id2 authorzhangsan contextprod !-- 生产环境专用变更 -- createIndex tableNameorder indexNameidx_order_status column namestatus/ /createIndex /changeSet执行时指定 contextliquibase --contextsprod update7.2 使用 Preconditions在执行前校验条件changeSet id1 authorzhangsan preConditions onFailHALT runningAs usernameliquibase/ tableExists tableNameuser/ /preConditions addColumn tableNameuser column namephone typevarchar(20)/ /addColumn /changeSet常用 preconditiontableExists、columnExists、sqlCheck、dbms、runningAs等。八、Liquibase 为什么比手写 SQL 脚本方便场景手写 SQL 脚本Liquibase团队协作谁改了啥全靠自觉容易漏执行自动追踪changelog 全在 Git 里多环境执行手动记录哪个脚本在哪执行过自动对比DATABASECHANGELOG只跑新的回滚基本没有回滚或靠备份恢复支持按 tag/时间/数量回滚幂等性重复执行会报错表已存在已执行的自动跳过不会报错跨数据库迁移MySQL 脚本在 Oracle 上不能用声明式 changelog 自动生成目标数据库的 SQLCI/CD 集成需要自己写脚本编排Maven/Gradle/Docker 开箱即用变更历史靠聊天记录和邮件DATABASECHANGELOG表就是完整的变更审计日志九、最佳实践一个 changeset 只做一件事— 便于回滚和排查问题永远不要修改已部署的 changeset— 创建新的 changeset 来变更。如果必须修改已部署的使用runOnChange属性changelog 文件放到 Git 里— 像源代码一样管理PR review 时可以审查数据库变更使用 tag 标记版本— 每次发版前打 tag方便回滚到特定版本先update-sql再update— 生产环境执行前先预览 SQL回滚逻辑一定要写— SQL 格式的手动写--rollback声明式格式尽量选支持自动回滚的 Change Type按版本目录组织 changelog— 如v1.0/、v1.1/、v2.0/十、总结Liquibase 是 Java 生态中最成熟的数据库版本控制工具没有之一。它让数据库变更变得可追踪— 每一次变更都有记录可重复— 任何环境跑一次就能复现可回滚— 出问题能快速恢复可协作— 团队通过 Git PR 管理数据库变更不管你是刚起步的个人项目还是多人协作的企业级应用Liquibase 都能让你的数据库管理更规范、更安全。参考资源Liquibase 官方文档Liquibase GitHub官方 Implementation Guide