2. Liquibase 核心概念:ChangeLog、ChangeSet、ID、Author、FileEncoding、Context、Label
Liquibase 的迁移体系建立在几个核心概念之上。理解这些概念是编写可维护、可追溯的数据库变更脚本的基础。本章将逐一拆解 ChangeLog、ChangeSet、ID、Author、FileEncoding、Context 和 Label 的定义、作用及最佳实践。
2.1 ChangeLog:迁移的根清单
ChangeLog 是 Liquibase 的入口文件,通常是一个 XML、YAML、JSON 或 SQL 格式的文件。它定义了数据库变更的版本清单,包含一个或多个 ChangeSet。Liquibase 通过解析 ChangeLog 来按顺序执行变更。
- 格式灵活:支持 XML(默认)、YAML、JSON、SQL 四种格式。
- 可嵌套:通过
<include>或<includeAll>标签引入子 ChangeLog,实现模块化管理。 - 版本控制:ChangeLog 文件本身应纳入 Git 等版本控制系统,作为数据库变更的“源代码”。
<!-- 示例:主 ChangeLog 文件 (db.changelog-master.xml) -->
<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-4.20.xsd">
<include file="changelogs/001-create-tables.xml" relativeToChangelogFile="true"/>
<include file="changelogs/002-add-indexes.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
2.2 ChangeSet:原子变更单元
ChangeSet 是 ChangeLog 中的最小执行单元,代表一次不可分割的数据库变更。每个 ChangeSet 包含一个或多个变更操作(如 createTable、addColumn、sql)。Liquibase 通过 ID + Author + FilePath 三元组来唯一标识一个 ChangeSet,并记录其是否已被执行。
<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 unique="true" nullable="false"/>
</column>
<column name="email" type="varchar(100)"/>
</createTable>
</changeSet>
2.3 ID 与 Author:唯一标识的基石
ID 和 Author 是 ChangeSet 的必填属性,与 ChangeLog 文件路径共同构成全局唯一标识。Liquibase 使用该标识在 DATABASECHANGELOG 表中记录执行状态,确保同一变更不会重复执行。
| 属性 | 说明 | 示例 | 注意事项 |
|---|---|---|---|
| ID | ChangeSet 的序号或标识符,在同一 ChangeLog 文件中应唯一 | 1, 001, 20250320-001 |
建议使用数字或日期前缀,便于排序和追溯 |
| Author | 编写该 ChangeSet 的作者名称 | zhangsan, dev-team |
建议使用统一的团队别名或系统用户名,避免使用个人昵称 |
2.4 FileEncoding:字符集一致性
FileEncoding 属性用于指定 ChangeLog 文件的字符编码。默认情况下,Liquibase 使用系统默认编码(通常为 UTF-8)。当 ChangeLog 中包含非 ASCII 字符(如中文注释、特殊符号)时,显式声明编码可避免乱码问题。
<databaseChangeLog
xmlns="..."
fileEncoding="UTF-8">
...
</databaseChangeLog>
fileEncoding 设置为 UTF-8,并在团队中统一使用 UTF-8 编码保存所有 ChangeLog 文件。
2.5 Context:环境隔离的开关
Context 允许为 ChangeSet 指定运行环境标签。Liquibase 在执行时通过 --contexts 参数过滤,只有匹配上下文的 ChangeSet 才会被执行。这解决了不同环境(开发、测试、生产)需要不同变更的问题。
<changeSet id="2" author="lisi" context="dev,test">
<insert tableName="config">
<column name="key" value="debug_mode"/>
<column name="value" value="true"/>
</insert>
</changeSet>
<changeSet id="3" author="lisi" context="prod">
<insert tableName="config">
<column name="key" value="debug_mode"/>
<column name="value" value="false"/>
</insert>
</changeSet>
执行命令示例:
# 仅执行 dev 和 test 环境的 ChangeSet
liquibase --contexts=dev,test update
# 仅执行 prod 环境的 ChangeSet
liquibase --contexts=prod update
2.6 Label:细粒度执行控制
Label 与 Context 类似,但更灵活。Label 可以附加到 ChangeSet 上,通过 --labels 参数进行包含或排除过滤。与 Context 的“环境”语义不同,Label 通常用于描述变更的“类型”或“特性”,如 schema-change、data-migration、hotfix。
| 特性 | Context | Label |
|---|---|---|
| 语义 | 环境(dev, test, prod) | 类型或特性(schema, data, hotfix) |
| 过滤方式 | 精确匹配(逗号分隔) | 支持表达式(!hotfix 排除,schema AND data 组合) |
| 典型用途 | 环境隔离 | 变更分类、灰度发布、紧急修复 |
<changeSet id="4" author="wangwu" labels="schema-change">
<addColumn tableName="user">
<column name="phone" type="varchar(20)"/>
</addColumn>
</changeSet>
<changeSet id="5" author="zhaoliu" labels="hotfix,data-migration">
<update tableName="user">
<column name="status" value="active"/>
<where>status IS NULL</where>
</update>
</changeSet>
执行命令示例:
# 仅执行 schema-change 标签的变更
liquibase --labels=schema-change update
# 执行除 hotfix 之外的所有变更
liquibase --labels=!hotfix update
2.7 核心概念关系图
下图展示了 ChangeLog、ChangeSet 及其属性之间的层级关系与执行流程:
2.8 核心概念对比总结
| 概念 | 层级 | 是否必填 | 作用域 | 典型值 |
|---|---|---|---|---|
| ChangeLog | 根文件 | 是 | 全局 | db.changelog-master.xml |
| ChangeSet | 变更单元 | 是 | 文件内 | 包含 createTable、addColumn 等 |
| ID | ChangeSet 属性 | 是 | ChangeSet 级别 | 1, 001, 20250320-001 |
| Author | ChangeSet 属性 | 是 | ChangeSet 级别 | zhangsan, dev-team |
| FileEncoding | ChangeLog 属性 | 否 | 文件级别 | UTF-8 |
| Context | ChangeSet 属性 | 否 | 环境过滤 | dev, test, prod |
| Label | ChangeSet 属性 | 否 | 类型过滤 | schema-change, hotfix |
DATABASECHANGELOG 表,其内容、ID 和 Author 均不应修改。如需调整,应创建新的 ChangeSet。