アプリケーション開発を進めていくと、データベースの構造を何度も変更することになります。
「新しいテーブルを追加したい」「カラムのデータ型を変更したい」「本番環境に反映した変更を元に戻したい」…こんなニーズに応えてくれるのがLiquibase(リキベース)です。
Liquibaseは、データベースの変更履歴を管理し、安全にマイグレーションを実行できる強力なツール。XML、YAML、JSON、SQLなど複数の形式で変更内容を記述できる柔軟性が魅力です。
この記事では、Liquibaseの基本から実践的な使い方まで、初心者の方にも分かりやすく解説していきます。
Liquibaseとは?基本を理解しよう

まずは、Liquibaseがどんなツールなのか見ていきましょう。
Liquibaseの概要
Liquibaseは、データベーススキーマの変更を管理するためのオープンソースツールです。
スキーマというのは、データベースの構造(テーブルやカラムの定義)のことですね。
Liquibaseを使うと、データベースの変更を履歴として記録しながら、段階的に構造を更新できます。さらに、変更を元に戻す「ロールバック」も簡単に行えるんです。
Liquibaseの特徴
Liquibaseには、こんな特徴があります。
| 特徴 | 説明 |
|---|---|
| 多様な記述形式 | XML、YAML、JSON、SQLで記述可能 |
| ロールバック対応 | 変更を簡単に元に戻せる |
| 環境別設定 | 開発・テスト・本番で異なる設定が可能 |
| データベース独立 | MySQL、PostgreSQL、Oracleなど主要DBに対応 |
| 自動ドキュメント生成 | 変更履歴を自動でドキュメント化 |
データベースマイグレーションの必要性
Liquibaseのようなマイグレーションツールがなぜ必要なのでしょうか。
手動での変更は危険
本番環境で手作業でSQL文を実行すると、ミスが起きやすくなります。
環境間の一貫性
開発、テスト、本番環境で同じ状態を保つのは、手動では困難です。
チーム開発での協調
複数人で開発していると、誰がどんな変更をしたか分からなくなります。
Liquibaseは、これらの課題を解決してくれる心強い味方なんです。
FlywayとLiquibaseの違い
データベースマイグレーションツールには、FlywayとLiquibaseという2大ツールがあります。
違いを理解して、自分のプロジェクトに合った方を選びましょう。
記述形式の違い
Flyway
基本的にSQLファイルのみで記述します。シンプルで分かりやすいのが特徴です。
Liquibase
XML、YAML、JSON、SQLの4つの形式から選べます。柔軟性が高いですね。
ロールバック機能
Flyway
無料版ではロールバック機能がありません。変更を戻すには、手動で新しいマイグレーションを作成する必要があります。
Liquibase
無料版でもロールバック機能が使えます。コマンド一つで変更を元に戻せるんです。
学習コスト
Flyway
SQLさえ書ければ使えるので、学習コストが低めです。
Liquibase
XMLやYAMLの記法を覚える必要があり、少し学習コストが高くなります。
どちらを選ぶべきか
Flywayがおすすめの場合
- シンプルに使いたい
- SQLに慣れている
- 小規模なプロジェクト
Liquibaseがおすすめの場合
- ロールバック機能が必要
- 複雑な変更管理が必要
- データベースに依存しないコードを書きたい
Liquibaseの仕組み
Liquibaseがどのように動作するのか、基本的な仕組みを理解しましょう。
changelogファイル
Liquibaseでは、データベースの変更内容をchangelog(チェンジログ)ファイルに記述します。
changelogファイルには、複数のchangeset(チェンジセット)が含まれます。
changesetは、1つの変更単位のこと。「テーブルを1つ作成する」「カラムを1つ追加する」といった変更が、それぞれ1つのchangesetになります。
データベーストラッキングテーブル
Liquibaseは、データベース内に自動的に2つの管理テーブルを作成します。
DATABASECHANGELOG
実行済みのchangesetを記録するテーブルです。
DATABASECHANGELOGLOCK
マイグレーション実行中に、他の実行を防ぐためのロックテーブルです。
これらのテーブルのおかげで、どの変更が実行済みか、Liquibaseが自動的に把握できるんです。
実行フロー
Liquibaseは、以下の流れでマイグレーションを実行します。
- changelogファイルを読み込む
- DATABASECHANGELOGテーブルで実行済みのchangesetを確認
- 未実行のchangesetを順番に実行
- 実行結果をDATABASECHANGELOGに記録
すでに実行されたchangesetは、再実行されません。
Liquibaseのセットアップ方法
それでは、実際にJavaプロジェクトでLiquibaseを使う方法を見ていきましょう。
Mavenプロジェクトでの導入
Mavenを使っている場合、pom.xmlに依存関係を追加します。
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.24.0</version>
</dependency>
Gradleプロジェクトでの導入
Gradleを使っている場合は、build.gradleに以下を追加します。
dependencies {
implementation 'org.liquibase:liquibase-core:4.24.0'
}
Spring Bootでの設定
Spring Bootを使っている場合は、application.propertiesで設定を行います。
application.propertiesの例
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml
設定項目の説明
- spring.liquibase.enabled:Liquibaseを有効化
- spring.liquibase.change-log:メインのchangelogファイルのパス
ディレクトリ構成
changelogファイルは、以下のような場所に配置します。
src/main/resources/
└── db/
└── changelog/
├── db.changelog-master.xml
├── changes/
│ ├── v1.0.0-create-users-table.xml
│ └── v1.0.1-add-email-column.xml
└── data/
└── initial-data.sql
マスターファイル(db.changelog-master.xml)で、個別のchangelogファイルを読み込む構成にするのが一般的です。
XMLでchangelogを書く方法

Liquibaseで最もよく使われるXML形式のchangelogを見ていきましょう。
マスターchangelogファイル
まず、すべての変更を統括するマスターファイルを作成します。
db.changelog-master.xml
<?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.24.xsd">
<include file="db/changelog/changes/v1.0.0-create-users-table.xml"/>
<include file="db/changelog/changes/v1.0.1-add-email-column.xml"/>
</databaseChangeLog>
<include>タグで、個別のchangelogファイルを読み込んでいます。
テーブル作成のchangeset
ユーザーテーブルを作成するchangesetの例です。
v1.0.0-create-users-table.xml
<?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.24.xsd">
<changeSet id="1" author="yamada">
<createTable tableName="users">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="username" type="VARCHAR(50)">
<constraints nullable="false"/>
</column>
<column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
</createTable>
</changeSet>
</databaseChangeLog>
要素の説明
- changeSet id:changesetを識別する一意のID
- author:作成者の名前
- createTable:テーブル作成を指示
- column:カラムの定義
- constraints:制約の設定
カラム追加のchangeset
既存のテーブルにカラムを追加する例です。
v1.0.1-add-email-column.xml
<?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.24.xsd">
<changeSet id="2" author="yamada">
<addColumn tableName="users">
<column name="email" type="VARCHAR(100)">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
<addColumn>タグで、既存のテーブルに新しいカラムを追加しています。
YAMLでchangelogを書く方法
XMLより簡潔に書けるYAML形式も人気があります。
YAMLのマスターファイル
db.changelog-master.yaml
databaseChangeLog:
- include:
file: db/changelog/changes/v1.0.0-create-users-table.yaml
- include:
file: db/changelog/changes/v1.0.1-add-email-column.yaml
XMLと比べて、とてもシンプルですね。
テーブル作成(YAML版)
v1.0.0-create-users-table.yaml
databaseChangeLog:
- changeSet:
id: 1
author: yamada
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: username
type: VARCHAR(50)
constraints:
nullable: false
- column:
name: created_at
type: TIMESTAMP
defaultValueComputed: CURRENT_TIMESTAMP
インデント(字下げ)で階層構造を表現します。
カラム追加(YAML版)
v1.0.1-add-email-column.yaml
databaseChangeLog:
- changeSet:
id: 2
author: yamada
changes:
- addColumn:
tableName: users
columns:
- column:
name: email
type: VARCHAR(100)
constraints:
nullable: false
YAMLは読みやすく、書きやすいのが特徴です。
SQLでchangelogを書く方法
生のSQLを直接使うこともできます。
SQLファイルの作成
v1.0.0-create-users-table.sql
--liquibase formatted sql
--changeset yamada:1
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
--rollback DROP TABLE users;
ポイント
- ファイルの先頭に
--liquibase formatted sqlを記述 --changeset author:idでchangesetを定義--rollbackでロールバック時の処理を記述
SQLをマスターファイルから読み込む
db.changelog-master.xml
<databaseChangeLog>
<include file="db/changelog/changes/v1.0.0-create-users-table.sql"/>
</databaseChangeLog>
XMLやYAMLのマスターファイルから、SQLファイルを読み込めます。
Liquibaseの実行方法
changelogファイルを作成したら、実際にマイグレーションを実行してみましょう。
Spring Bootでの自動実行
Spring Bootを使っている場合、アプリケーション起動時に自動的にLiquibaseが実行されます。
mvn spring-boot:run
未実行のchangesetが自動的に適用されます。
コマンドラインでの実行
Liquibaseは、コマンドラインツールとしても使えます。
Mavenプラグインを使う場合
mvn liquibase:update
Gradleプラグインを使う場合
gradle liquibaseUpdate
プログラムから実行
Javaコード内で、プログラム的に実行することもできます。
import liquibase.Liquibase;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.resource.ClassLoaderResourceAccessor;
import java.sql.Connection;
import java.sql.DriverManager;
public class LiquibaseMigration {
public static void main(String[] args) throws Exception {
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb",
"root",
"password"
);
Database database = DatabaseFactory.getInstance()
.findCorrectDatabaseImplementation(new JdbcConnection(connection));
Liquibase liquibase = new Liquibase(
"db/changelog/db.changelog-master.xml",
new ClassLoaderResourceAccessor(),
database
);
liquibase.update("");
connection.close();
}
}
ロールバック機能の使い方

Liquibaseの大きな魅力の一つが、ロールバック機能です。
ロールバックの基本
changesetを元に戻すには、以下のコマンドを実行します。
mvn liquibase:rollback -Dliquibase.rollbackCount=1
これで、最後に実行した1つのchangesetがロールバックされます。
日付指定でのロールバック
特定の日時まで戻すこともできます。
mvn liquibase:rollback -Dliquibase.rollbackDate=2024-01-01
2024年1月1日の状態まで戻ります。
タグを使ったロールバック
あらかじめタグを設定しておくと、そのタグまで戻せます。
タグの設定
<changeSet id="3" author="yamada">
<tagDatabase tag="version-1.0"/>
</changeSet>
タグまでロールバック
mvn liquibase:rollback -Dliquibase.rollbackTag=version-1.0
ロールバック用SQLの自動生成
Liquibaseは、XML/YAML形式で書いたchangesetから、ロールバック用のSQLを自動生成してくれます。
例えば、createTableに対してはDROP TABLEが自動的に用意されるんです。
カスタムのロールバック処理が必要な場合は、明示的に指定できます。
<changeSet id="4" author="yamada">
<sql>
UPDATE users SET status = 'active' WHERE status IS NULL;
</sql>
<rollback>
UPDATE users SET status = NULL WHERE status = 'active';
</rollback>
</changeSet>
便利な機能とコマンド
Liquibaseには、他にも便利な機能がたくさんあります。
status:状態確認
現在のマイグレーション状態を確認できます。
mvn liquibase:status
どのchangesetが実行済みで、どれが未実行かが表示されます。
validate:検証
changelogの内容が正しいか検証します。
mvn liquibase:validate
diff:差分確認
2つのデータベースの差分を確認できます。
mvn liquibase:diff
本番環境と開発環境の違いを調べるときに便利です。
generateChangeLog:既存DBからchangelog生成
すでに存在するデータベースから、changelogを自動生成できます。
mvn liquibase:generateChangeLog
既存プロジェクトにLiquibaseを導入するときに役立ちます。
preconditions:前提条件の設定
changesetを実行する前に、条件をチェックできます。
<changeSet id="5" author="yamada">
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="users"/>
</not>
</preConditions>
<createTable tableName="users">
<!-- カラム定義 -->
</createTable>
</changeSet>
この例では、usersテーブルが存在しない場合のみ実行されます。
ベストプラクティス
Liquibaseを効果的に使うためのポイントをまとめました。
changesetは小さく保つ
1つのchangesetには、1つの論理的な変更だけを含めましょう。
良い例
<!-- 1つのテーブル作成のみ -->
<changeSet id="1" author="yamada">
<createTable tableName="users"/>
</changeSet>
悪い例
<!-- 複数の無関係な変更を詰め込んでいる -->
<changeSet id="1" author="yamada">
<createTable tableName="users"/>
<createTable tableName="products"/>
<addColumn tableName="orders"/>
</changeSet>
IDの命名規則を統一
changesetのIDは、チーム内で統一したルールで付けましょう。
- 連番:1, 2, 3…
- 日時:20240101-1, 20240101-2…
- バージョン:v1.0.0-1, v1.0.0-2…
コンテキストの活用
環境ごとに実行するchangesetを分けられます。
<changeSet id="6" author="yamada" context="dev">
<!-- 開発環境でのみ実行 -->
<insert tableName="users">
<column name="username" value="test_user"/>
</insert>
</changeSet>
<changeSet id="7" author="yamada" context="prod">
<!-- 本番環境でのみ実行 -->
</changeSet>
実行時にコンテキストを指定します。
mvn liquibase:update -Dliquibase.contexts=dev
ロールバックテストを行う
本番環境で実行する前に、ロールバックが正しく動作するか確認しましょう。
# マイグレーション実行
mvn liquibase:update
# ロールバックテスト
mvn liquibase:rollback -Dliquibase.rollbackCount=1
# 再度マイグレーション
mvn liquibase:update
バージョン管理
changelogファイルは、Gitなどのバージョン管理システムに必ずコミットしましょう。
データベースの変更履歴を、コードと一緒に管理できます。
トラブルシューティング
Liquibaseを使う際によく遭遇する問題と、その解決方法です。
changelogが見つからない
症状FileNotFoundExceptionなどのエラーが出る。
原因と対処法
- パスが間違っている
application.propertiesのパスを確認 - ファイルが配置されていない
src/main/resources/db/changelog/に正しく配置されているか確認
checksum検証エラー
症状
「Checksum validation failed」というエラーが表示される。
原因
実行済みのchangesetを変更した。
対処法
changesetは変更せず、新しいchangesetを追加するのが原則です。
どうしても修正が必要な場合は、以下のコマンドでチェックサムをクリアします。
mvn liquibase:clearCheckSums
ロックエラー
症状
「Waiting for changelog lock」というメッセージが出て処理が進まない。
原因
前回のマイグレーション実行が異常終了し、ロックが残っている。
対処法
mvn liquibase:releaseLocks
このコマンドで、ロックを強制解除できます。
循環参照エラー
症状
「Circular reference detected」というエラーが出る。
原因
マスターchangelogファイルの<include>で、ファイルの読み込み順序に問題がある。
対処法
依存関係を整理して、正しい順序で読み込むようにします。
まとめ
Liquibaseについて解説してきました。
重要なポイント
- LiquibaseはXML、YAML、JSON、SQLで記述できる柔軟なマイグレーションツール
- 無料版でもロールバック機能が使える
- changesetで変更を管理し、実行履歴はDATABASECHANGELOGに記録される
- Spring Bootでは自動的にマイグレーションが実行される
- マスターchangelogファイルで複数のファイルを統合管理できる
- 前提条件やコンテキストで、柔軟な実行制御が可能
- changesetは小さく保ち、ロールバックテストを忘れずに行う
Liquibaseは、最初は複雑に感じるかもしれません。しかし、ロールバック機能や豊富な機能を使いこなせば、データベース管理が格段に楽になります。
まずは簡単なテーブル作成から始めて、徐々に高度な機能にも挑戦してみてください。安全で確実なデータベース管理を実現しましょう!

コメント