4. ChangeLog 文件结构:四种格式详解
ChangeLog 是 Liquibase 迁移的核心清单文件,它按顺序记录所有数据库变更。Liquibase 原生支持四种格式:XML、YAML、JSON 和 SQL。选择哪种格式取决于团队习惯、工具链集成度以及对可读性的要求。
核心原则:无论使用哪种格式,ChangeLog 的语义等价——即变更集(changeset)的 ID、作者、文件路径和变更顺序必须一致。格式只是序列化方式不同,Liquibase 引擎最终都会解析为统一的内存模型。
4.1 四种格式概览与对比
| 特性 | XML | YAML | JSON | SQL |
|---|---|---|---|---|
| 官方推荐度 | 最高(原生格式) | 高 | 中 | 中(面向 DBA) |
| 可读性 | 结构化,标签冗余 | 简洁,缩进敏感 | 紧凑,括号多 | 纯 SQL 语句 |
| IDE 支持 | 完善(XSD 校验) | 良好 | 良好 | 标准 SQL 高亮 |
| 变更类型覆盖 | 全部 refactoring 标签 | 全部 | 全部 | 仅原生 SQL |
| 版本控制友好度 | 高(标签 diff 清晰) | 高(行级 diff) | 中(行级 diff 但括号多) | 高(纯文本) |
| 适用场景 | 企业级、CI/CD 集成 | DevOps 团队、配置即代码 | API 驱动、动态生成 | DBA 主导、遗留系统迁移 |
4.2 XML 格式 ChangeLog
XML 是 Liquibase 的原生格式,拥有最完整的 XSD 校验支持。所有 refactoring 标签(如 createTable、addColumn)都有明确的 XML 元素映射,IDE 自动补全和校验体验最佳。
<?xml version="1.0" 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-4.23.xsd">
<changeSet id="001" author="zhang.san">
<createTable tableName="users">
<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(255)"/>
</createTable>
</changeSet>
<changeSet id="002" author="zhang.san">
<addColumn tableName="users">
<column name="status" type="varchar(20)" defaultValue="ACTIVE"/>
</addColumn>
</changeSet>
</databaseChangeLog>
XML 最佳实践:
- 始终声明
databaseChangeLog根元素并引用最新 XSD,确保 IDE 和 CI 工具能校验语法。 - 每个
changeSet必须包含id和author属性,这是数据库追踪的唯一键。 - 使用
preConditions标签保护敏感变更,避免重复执行导致错误。
4.3 YAML 格式 ChangeLog
YAML 格式以缩进层级代替 XML 的闭合标签,代码量减少约 30%-40%,在 DevOps 团队中非常流行。Liquibase 从 3.1 版本开始原生支持 YAML。
databaseChangeLog:
- changeSet:
id: 001
author: li.si
changes:
- createTable:
tableName: orders
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: user_id
type: bigint
constraints:
nullable: false
- column:
name: total_amount
type: decimal(10,2)
- changeSet:
id: 002
author: li.si
changes:
- addForeignKeyConstraint:
baseTableName: orders
baseColumnNames: user_id
referencedTableName: users
referencedColumnNames: id
constraintName: fk_orders_users
YAML 避坑指南:
- 缩进必须使用空格,禁止使用 Tab。建议统一为 2 个空格缩进。
- 列表项前的
-后面必须跟一个空格,否则解析失败。 - 字符串值如果包含特殊字符(如
:、#),建议用双引号包裹。
4.4 JSON 格式 ChangeLog
JSON 格式适合程序化生成 ChangeLog 的场景,例如从数据库逆向工程工具导出、或由 CI/CD 管道动态拼接变更集。Liquibase 从 3.5 版本开始支持 JSON。
{
"databaseChangeLog": [
{
"changeSet": {
"id": "001",
"author": "wang.wu",
"changes": [
{
"createTable": {
"tableName": "products",
"columns": [
{
"column": {
"name": "id",
"type": "bigint",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},
{
"column": {
"name": "name",
"type": "varchar(200)",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "price",
"type": "decimal(10,2)"
}
}
]
}
}
]
}
}
]
}
JSON 使用建议:JSON 格式不支持注释,因此建议在 ChangeLog 头部使用
context 或 labels 属性来标记变更集的用途。对于需要大量人工审阅的团队,优先选择 XML 或 YAML。
4.5 SQL 格式 ChangeLog
SQL 格式是最直接的方式——你直接编写原生 SQL 语句,Liquibase 负责追踪执行状态。这种方式对 DBA 最友好,但失去了跨数据库兼容性。
-- liquibase formatted sql
-- changeset zhao.liu:001
CREATE TABLE categories (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- changeset zhao.liu:002
ALTER TABLE categories ADD COLUMN parent_id BIGINT;
ALTER TABLE categories ADD CONSTRAINT fk_categories_parent
FOREIGN KEY (parent_id) REFERENCES categories(id);
-- changeset zhao.liu:003
CREATE INDEX idx_categories_name ON categories(name);
SQL 格式关键规则:
- 文件第一行必须是
-- liquibase formatted sql,否则 Liquibase 不会识别。 - 每个变更集以
-- changeset author:id注释行开始,后面紧跟 SQL 语句。 - SQL 语句之间用空行分隔,Liquibase 默认以分号
;作为语句结束符。 - 可以使用
-- rollback注释块定义回滚 SQL,增强迁移安全性。
4.6 四种格式的解析流程对比
4.7 格式选择决策树
在实际项目中,选择哪种 ChangeLog 格式通常遵循以下决策逻辑:
- 团队构成:如果团队以 DBA 为主,优先选择 SQL 格式;如果以应用开发为主,优先选择 XML 或 YAML。
- 工具链集成:如果使用 Spring Boot + Liquibase 自动配置,XML 开箱即用;如果使用 Gradle/Maven 插件,YAML 更简洁。
- 跨数据库需求:如果需要支持多种数据库(如开发用 H2、生产用 PostgreSQL),必须使用 XML/YAML/JSON 格式,避免 SQL 格式的方言差异。
- 自动化程度:如果 ChangeLog 由代码生成器或 CI 管道动态生成,JSON 格式最易拼接。
重要提醒:不要在同一个 ChangeLog 文件中混用多种格式。Liquibase 允许通过
include 或 includeAll 引用不同格式的子文件,但单个文件必须保持格式统一。混合格式会导致解析器切换错误,引发不可预期的失败。