數據庫結構變更無版本控制是運維大坑。Liquibase 以「變更集」為核心,支持 XML/YAML/SQL 多格式、多環境、回滾、分支合並,是資料庫 DevOps 首選工具。
id、author、context、rollbackinclude 子文件,控制執行順序database/
├── db.changelog-master.xml # 總入口
├── Release-2024-01/
│ ├── 001_create_users_table.sql
│ ├── 002_add_email_index.sql
│ └── 003_insert_init_data.sql
├── Release-2024-02/
│ ├── 010_alter_orders_add_status.sql
│ └── 011_create_order_items_table.sql
└── contexts/
├── dev.xml
├── test.xml
└── prod.xml
db.changelog-master.xml<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="https://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.liquibase.org/xml/ns/dbchangelog
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
<preConditions>
<dbms type="mysql"/>
</preConditions>
<!-- 按發布版本順序 include,確保執行順序 -->
<include file="Release-2024-01/001_create_users_table.sql" relativeToChangelogFile="true"/>
<include file="Release-2024-01/002_add_email_index.sql" relativeToChangelogFile="true"/>
<include file="Release-2024-01/003_insert_init_data.sql" relativeToChangelogFile="true"/>
<include file="Release-2024-02/010_alter_orders_add_status.sql" relativeToChangelogFile="true"/>
<include file="Release-2024-02/011_create_order_items_table.sql" relativeToChangelogFile="true"/>
</databaseChangeLog>
-- Release-2024-01/001_create_users_table.sql
--liquibase formatted sql
--changeset zhangsan:202401_001_create_users_table context:dev,test,prod
CREATE TABLE `users` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`email` VARCHAR(100) NOT NULL,
`password_hash` CHAR(60) NOT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--rollback DROP TABLE `users`;
<changeSet author="lisi" id="202401_002_add_email_index" context="dev,test,prod">
<createIndex tableName="users" indexName="idx_email_domain">
<column name="email"/>
</createIndex>
<rollback>
<dropIndex tableName="users" indexName="idx_email_domain"/>
</rollback>
</changeSet>
| 操作 | 命令 | 說明 |
|---|---|---|
| 校驗語法 | liquibase validate --changelog-file=db.changelog-master.xml | CI/CD 必跑步驟 |
| 生成文檔 | liquibase dbDoc --changelog-file=... --output-dir=./doc | 輸出 HTML 數據字典 |
| 執行遷移 | liquibase update --changelog-file=... --contexts=prod | 按 context 過濾執行 |
| 打標籤 | liquibase tag Release-2024-01 --changelog-file=... | 標記發布版本,便於回滾 |
| 回滾到標籤 | liquibase rollback Release-2024-01 --changelog-file=... | 撤銷該標籤後所有變更 |
| 回滾到時間 | liquibase rollbackToDate "2024-01-15 10:00:00" --changelog-file=... | 時間點恢復 |
| 回滾條數 | liquibase rollbackCount 3 --changelog-file=... | 撤銷最近 3 個 ChangeSet |
| 生成遷移 SQL | liquibase updateSQL --changelog-file=... > migrate.sql | 審核/離線執行 |
| 對比兩庫 | liquibase diff --referenceUrl=jdbc:mysql://prod/... --url=jdbc:mysql://test/... | 結構差異報告 |
| 反向生成 Changelog | liquibase generateChangeLog --changelog-file=... --url=jdbc:mysql://prod/... | 現有庫納管 |
| 列出鎖 | liquibase listLocks | 排查卡死 |
| 釋放鎖 | liquibase releaseLocks | 強制解鎖 |
context:dev:僅開發環境執行(如測試數據插入)context:test,prod:測試+生產執行(核心結構變更)context:prod:僅生產執行(敏感數據遷移、權限變更)--contexts=prod 只跑 prod 標記的 ChangeSetDROP COLUMN)需手寫補償 SQL作者_日期_序號_描述validate → updateSQL(審核) → update(自動/手動確認)liquibase \ --driver=com.mysql.cj.jdbc.Driver \ --url="jdbc:mysql://10.0.1.10:3306/prod_db?useUnicode=true&characterEncoding=utf8mb4&useSSL=false&serverTimezone=UTC" \ --username=liquibase_user \ --password='LiquiPassw0rd!' \ --changelog-file=db.changelog-master.xml \ --contexts=prod \ --logLevel=INFO \ update
引入 Liquibase,讓數據庫結構變更像代碼一樣「可版本、可審核、可回滾、可追溯」。