LabHub

ブログ

DB マイグレーションツール 2026 — Atlas / Flyway / Liquibase / Bytebase / pgroll / Squawk / gh-ost 徹底比較

한국어English日本語

プロローグ — 「マイグレーション一行で 5 分ダウン」

2026 年のあるチームのポストモーテム。

23:14、いつも通りのデプロイ。ALTER TABLE orders ADD COLUMN status_v2 VARCHAR(32) NOT NULL DEFAULT 'pending'。23:14:08、プライマリでロック取得。23:14:09、すべてのクエリがキューに溜まり始める。23:14:42、バックエンドの connection pool が枯渇、5xx が始まる。23:19:31、マイグレーション終了。23:19:34、キュー解消、復帰。5 分 22 秒のダウン。 テーブルには 4 億行あった。

これは 2026 年でもよくある光景だ。ツールは十分すぎるほどある — Flyway、Liquibase、Atlas、Bytebase、pgroll、Squawk、gh-ost、pt-osc、Reshape、dbmate、golang-migrate、Diesel、Alembic、Prisma Migrate、Drizzle Kit。それでも 「どのマイグレーションが安全か」をツールが教えてくれなければ、5 分ダウンは繰り返される。

この記事では 2026 年の DB マイグレーションツールの地図を描く。誰が何を得意で、誰が何を不得意とするか、そして自分のチームは何を選ぶべきかまで。


1 章 · 2026 年 DB マイグレーション地図 — 宣言型 vs 命令型 vs オンライン変更

まず全体像。すべてのマイグレーションツールは三つの軸のどこに立つかで分かれる。

軸 1: 宣言型 (declarative) vs 命令型 (imperative)

宣言型は Terraform がインフラに対して行ったことを DB スキーマに対して行う。利点: スキーマがコードとして一望できる。欠点: 生成された ALTER が常に安全だとは限らない (rename を drop+add に分解してしまうなど)。

軸 2: オンライン (online) vs オフライン (offline)

小さなテーブル (数十万行以下) ならオフラインがシンプル。大きなテーブル (数億行・高トラフィック) ではオンラインが必須。

軸 3: forward-only vs reversible

2026 年のシニアたちの共通認識: forward-only + 短く安全な変更の連続 が reversible より現実的。down は「いま追加した空のカラムを drop する」程度までしか意味を持たない。

一枚要約

ツールモデルオンライン?言語・対象推奨用途
Atlas宣言型直接は不可、統合ありマルチ DB宣言型スキーマ + CI
Flyway 11命令型不可Java 親和エンタープライズ標準
Liquibase 4.30命令型 + メタ不可Java・XML/YAML大企業・マルチ DB
Sqitch命令型 + DAG不可DB 中立依存性明示型
Bytebase 3両方 + ワークフロー統合ありマルチ DBDB DevOps・レビュー
Squawkリンタn/aPostgresCI ゲート
pgroll宣言型 + expand/contractPostgres無停止 Postgres
gh-ostonline changeMySQL大規模 MySQL
pt-osconline changeMySQLクラシック MySQL
Reshapeonline changePostgresRust・無停止
dbmate命令型不可マルチ DB・Go CLI軽量 CLI
golang-migrate命令型不可Go・マルチ DBGo 標準
Diesel命令型 + ORM不可RustRust 親和
Alembic命令型 + 自動生成不可Python・SQLAlchemyPython 標準
Prisma Migrate両方不可TypeScriptNode 親和
Drizzle Kit宣言型 + 命令型不可TypeScriptTS・軽量

これが 2026 年の地図。ここから一マスずつ見ていく。


2 章 · Expand-Contract パターン + よくある落とし穴

ツールを選ぶ前に パターン を理解しておく必要がある。良いツールでも間違ったパターンで使えばロックする。

Expand-Contract (Parallel Change)

無停止マイグレーションの中核パターン。三段階に分割する。

  1. Expand: 旧スキーマと新スキーマが共存するように追加だけする。drop はしない。
  2. Migrate: コードが新スキーマで読み書きするようにする。バックフィルで過去データを新スキーマへコピー。
  3. Contract: すべてのコードが新スキーマだけを使うと確認できたら、旧スキーマを drop。

例 — カラムの rename (emailemail_address)。

pgroll・Reshape・gh-ost はこれを既定モデルとして自動化している。それ以外のツールでは人がマイグレーションを 3 つに分けないといけない。

よくある落とし穴 (foot-guns)

1) NOT NULL を追加 (大きなテーブル)

Postgres 11+ では ALTER TABLE ... ADD COLUMN x INT NOT NULL DEFAULT 0 はメタデータだけ書き換える (速い)。しかし ALTER TABLE ... ALTER COLUMN x SET NOT NULL はテーブル全体をスキャンしながら ACCESS EXCLUSIVE ロック。4 億行なら分単位でロック。

2) カラムの rename

3) 型変更 (INT → BIGINT)

4) インデックス追加

5) デフォルト値変更 (Postgres 11 未満 / 一部の型)

6) Foreign key 追加

7) 大きな DELETE / UPDATE

要点: マイグレーションツールは「スクリプトを順に走らせる何か」にすぎず、安全性を保証しない。 安全性は上のパターン + (Squawk のような) リンタ + レビューから生まれる。


3 章 · Atlas (Ariga) — 宣言型スキーマ管理の代表

Atlas (atlasgo.io) は 2022 年に始まり、2024-2025 年にシェアを急速に伸ばした。HashiCorp の Terraform を DB スキーマに対して行うツール。

モデル

schema.hcl (または SQL / JSON) に望ましいスキーマを書く。Atlas が現在の DB と比較して差分を計算し ALTER 文を生成する。

schema "public" {}

table "users" {
  schema = schema.public
  column "id" {
    type = bigint
    null = false
  }
  column "email" {
    type = varchar(255)
    null = false
  }
  primary_key { columns = [column.id] }
  index "idx_users_email" {
    columns = [column.email]
    unique  = true
  }
}

CLI は二つのモードを持つ。

強み

弱み

推奨用途

2026 年時点で Atlas は 宣言型陣営の事実上の標準


4 章 · Flyway 11 — Java 陣営のクラシック

Flyway は 2010 年から、JBoss / Spring Boot エコシステムの標準。2024 年に Redgate が買収、11.x はモジュール整理と新規データベースアダプタが中心。

モデル

V{version}__{description}.sql 命名規約。素直な命令型。

db/migration/
  V1__create_users.sql
  V2__add_email_index.sql
  V3__add_orders.sql
  R__create_view_active_users.sql   # Repeatable
  U2__rollback_email_index.sql       # Undo (Teams)

DB の flyway_schema_history テーブルがどの V を実行済みかを追跡。flyway migrate で未適用分のみを順に適用。

強み

弱み

推奨用途

2026 年でも JVM 陣営のデフォルト。ただし新規プロジェクトが Flyway だけを使うケースは減り、Atlas / Squawk と組み合わせる例が増えた。


5 章 · Liquibase 4.30 — XML / YAML 親和

Liquibase は Flyway のライバル。2006 年から、4.30 (2025-2026) は changelog フォーマット・DB サポート・UX 改善が中心。

モデル

changelog ファイルに changeSet を列挙する。フォーマットは XML・YAML・JSON・SQL のいずれも可能。

databaseChangeLog:
  - changeSet:
      id: 1
      author: alice
      changes:
        - createTable:
            tableName: users
            columns:
              - column:
                  name: id
                  type: BIGINT
                  autoIncrement: true
                  constraints: { primaryKey: true, nullable: false }
              - column:
                  name: email
                  type: VARCHAR(255)
                  constraints: { nullable: false, unique: true }
      rollback:
        - dropTable: { tableName: users }

強み

弱み

Flyway vs Liquibase 一行で

2026 年時点で二者はほぼ拮抗、ただし新規プロジェクトは Atlas に移る流れが明確。


6 章 · Sqitch — 依存性ベースの旧学派

Sqitch (sqitch.org) は 2012 年に David Wheeler が作った「Git のようなマイグレーションツール」。バージョン番号ではなく依存グラフ でマイグレーションを追跡する。

モデル

各変更には名前がある。sqitch add appchanges で 3 つのファイルが生成される。

deploy/appchanges.sql    -- 適用 SQL
revert/appchanges.sql    -- 巻き戻し SQL
verify/appchanges.sql    -- 検証 SELECT

sqitch.plan に依存性を明示する。

add_users 2026-05-16T12:00:00Z alice
add_orders [add_users] 2026-05-16T13:00:00Z alice  -- add_users に依存

sqitch deploy は依存性を満たす順序で適用。sqitch verify は verify SQL を実行して本当に適用されたかを確認する。

強み

弱み

推奨用途

2026 年の Sqitch は ニッチだが忠誠度の高い ツール。PostgreSQL のコアコントリビュータの一部は今も愛用。


7 章 · Bytebase 3 — DB DevOps + レビュー

Bytebase (bytebase.com) は 2021 年スタート、2025 年に 3.x へジャンプ。コンセプトは 「DB 向けの GitLab / GitHub」

モデル

Web UI + GitOps。マイグレーション SQL を PR として上げると Bytebase が:

  1. 自動 lint (SQL Review、Squawk スタイルのルールセット)。
  2. 承認ワークフロー (DBA がレビュー)。
  3. ステージ別自動デプロイ (dev → staging → prod)。
  4. スキーマドリフト検出 (Bytebase が知らない変更が prod に入ったらアラート)。
  5. データマスキング・アクセスコントロール (誰がどのカラムを見られるか)。

強み

弱み

推奨用途

2026 年の Bytebase は DB DevOps の事実上の先頭。PlanetScale / Neon などのサーバレス DB が自前 UI を作って競合してきているが、on-prem / マルチクラウドは Bytebase 優位。


8 章 · Squawk — Postgres マイグレーションリンタ

Squawk (squawkhq.com) は Steve Dignam が 2020 年に作った小さな OSS。マイグレーション SQL を読んで危険なパターンを検出する。 マイグレーションツールではなくリンタ。

モデル

squawk migration.sql

危険なパターンを見つけるとエラー/警告。

migration.sql:1:1: warning: adding-not-nullable-field
  ALTER TABLE "user" ADD COLUMN "email" TEXT NOT NULL
  Adding a NOT NULL field requires a table rewrite ...
  Use ADD COLUMN ... DEFAULT NULL, backfill, then ALTER ... SET NOT NULL.

検出ルール (Postgres 中心、30+)

強み

弱み

推奨用途

2026 年のシニア共通認識: Postgres を使うなら Squawk はデフォルト。 ツール選択と無関係に CI に入れる。


9 章 · pgroll (Xata) — 無停止 Postgres マイグレーション

pgroll (github.com/xataio/pgroll) は Xata が 2023-2024 年に OSS として公開。野心は 「expand-contract をツール自身が自動化する」

モデル

JSON でマイグレーションを定義する。pgroll が自動的に view + トリガを作って、旧バージョンと新バージョンのスキーマを同時に露出する。

{
  "name": "rename_email_column",
  "operations": [
    {
      "rename_column": {
        "table": "users",
        "column": "email",
        "to": "email_address"
      }
    }
  ]
}

pgroll start で開始 → 二つのバージョンが共存 (view で露出) → pgroll complete で旧カラム削除。途中で pgroll rollback も可能。

動作原理

  1. pgroll start が新カラム/テーブル/インデックスを追加 + view を生成。
  2. 旧 view = 旧スキーマ、新 view = 新スキーマ。コードは SET search_path でどちらの view を使うか選ぶ。
  3. トリガが双方向にデータを同期 (旧カラムへの書き込みは新カラムにも、新カラムへの書き込みは旧カラムにも)。
  4. バックフィルがバックグラウンドで旧データを新カラムにコピー。
  5. すべてのトラフィックが新 view に移ったら pgroll complete で旧カラム drop。

強み

弱み

推奨用途

2026 年の pgroll は Postgres 無停止マイグレーションの best bet。ただし安定性は gh-ost (MySQL) にはまだ及ばない。


10 章 · gh-ost / pt-online-schema-change / Reshape — オンラインスキーマ変更

大テーブル + ライブトラフィック = オンラインスキーマ変更が必要。三つのツール。

gh-ost (GitHub、MySQL)

GitHub が 2016 年に作って OSS 化。トリガなし、binlog ベース。

動作:

  1. シャドウテーブルを新スキーマで作成。
  2. 旧テーブルの行を chunk 単位でシャドウに INSERT。
  3. binlog を読んで進行中の変更 (INSERT / UPDATE / DELETE) をシャドウにも適用。
  4. カットオーバー: 短いロックで旧テーブル ↔ シャドウを atomic に swap。
gh-ost \
  --user="root" --password="..." \
  --host=primary.db \
  --database="app" --table="orders" \
  --alter="ADD COLUMN status_v2 VARCHAR(32) NOT NULL DEFAULT 'pending'" \
  --execute

pt-online-schema-change (Percona、MySQL)

Percona Toolkit の一部。トリガベース。

動作:

  1. シャドウテーブル + 旧テーブルに INSERT / UPDATE / DELETE トリガを設置。
  2. chunk 単位で旧 → シャドウへコピー。
  3. カットオーバー: 二回の RENAME TABLE で swap。

Reshape (Postgres、Rust)

2022 年に Fabian Lindfors が作った Rust 製ツール。Postgres 向け expand-contract。

動作: pgroll と似ている。SQL ではなく TOML でマイグレーションを定義 + view + トリガで旧/新を共存。

[[actions]]
type = "add_column"
table = "users"
column = "email_address"
data_type = "text"
nullable = true

三者比較

gh-ostpt-oscReshapepgroll
DBMySQLMySQLPostgresPostgres
トリガなしありありあり
binlogありなしなしなし
活動度 (2026)
推奨大規模 MySQLgh-ost が無理なケース(回避)Postgres

2026 年の合意: MySQL は gh-ost がデフォルト、フォールバックが pt-osc。Postgres は pgroll が新興標準。


11 章 · dbmate / golang-migrate / Diesel / Alembic — 言語別オプション

各言語陣営のデフォルト。

dbmate (Go、マルチ DB)

amacneil/dbmate。一ファイルの Go バイナリ、CLI デザインがきれい。

dbmate new add_users
# db/migrations/20260516120000_add_users.sql が生成される

ファイルは up / down 二セクション。

-- migrate:up
CREATE TABLE users (id BIGINT PRIMARY KEY, email TEXT NOT NULL);

-- migrate:down
DROP TABLE users;

golang-migrate (Go、マルチ DB)

golang-migrate/migrate。CLI + Go ライブラリ。

migrations/
  000001_create_users.up.sql
  000001_create_users.down.sql

dbmate vs golang-migrate — 2024-2025 年に dbmate に移行したチームが増えた。新規 Go プロジェクトは dbmate がデフォルト (または Atlas)。

Diesel migrations (Rust)

Diesel ORM の一部。diesel migration generate add_usersup.sql / down.sql が生成される。

Alembic (Python、SQLAlchemy)

SQLAlchemy のマイグレーションツール。マイグレーションを Python コードで定義。

def upgrade():
    op.add_column('users', sa.Column('email', sa.String(255), nullable=False))

def downgrade():
    op.drop_column('users', 'email')

2026 年でも Python / Django は Django migrationsPython / FastAPI / SQLAlchemy は Alembic がデフォルト。


12 章 · Prisma Migrate / Drizzle Kit — TypeScript 陣営

Node / TypeScript は分裂状態。二強。

Prisma Migrate

Prisma ORM の一部。schema.prisma にモデルを書き、prisma migrate dev でマイグレーション生成/適用。

model User {
  id    BigInt  @id @default(autoincrement())
  email String  @unique
}

Drizzle Kit

Drizzle ORM の一部。コード (TypeScript) でスキーマ定義 → drizzle-kit generate で SQL 差分を生成。

export const users = pgTable("users", {
  id: bigserial("id").primaryKey(),
  email: varchar("email", { length: 255 }).notNull().unique(),
});

2026 年の TS 合意:


13 章 · 誰が何を選ぶべきか — ディシジョンツリー

状況推奨
単一アプリ、Postgres、トラフィック少dbmate または golang-migrate + Squawk
単一アプリ、MySQL、トラフィック少Flyway または dbmate
Java / Spring BootFlyway (または Liquibase) + Squawk
Node / TypeScript、フルスタックPrisma + 規模到達時に Atlas
Node / TypeScript、エッジDrizzle Kit + Squawk
Python / DjangoDjango migrations
Python / FastAPIAlembic
RustDiesel または SQLx + dbmate
Go、新規プロジェクトAtlas (宣言型) または dbmate (シンプル)
マイクロサービス 50+Bytebase + 各サービスが選んだツール
大規模 Postgres、無停止必須pgroll + Squawk + Atlas
大規模 MySQL、無停止必須gh-ost + Flyway + Squawk-MySQL 代替
DBA チームあり、レビューワークフローBytebase 中心
クロス DB (Postgres + MySQL + Oracle)Liquibase または Bytebase
累積マイグレーション 1000+Sqitch (依存グラフ)

よくあるアンチパターン


14 章 · 韓国 / 日本の事例 — トス / カカオ / メルカリ

トス (Toss)

トスは 2023 年のカンファレンス (SLASH) で gh-ost を MySQL で広範に使う ことを公開。決済ドメインは 24/7 なのでロックは即売上損失。gh-ost で chunk サイズ・throttle をドメインごとにチューニング。

2025-2026 年のトスでは一部新規 Postgres サービスで pgroll を検討中との発表あり。Squawk はすべての新規マイグレーション PR の必須 CI ステップ。

カカオ (Kakao)

カカオはメッセンジャー・ペイ・バンクそれぞれ DB 戦略が違う。カカオバンクは Oracle ベースで Liquibase + 独自ワークフロー。カカオペイの一部新規サービスは Flyway + gh-ost (MySQL) の組み合わせ。カカオメッセンジャーは独自分散ストレージなので一般マイグレーションツールの範囲外。

2024 年にカカオの一部チームが Atlas を導入して Go バックエンドを統一したとの話がカンファレンスで出た。

メルカリ (Mercari、日本)

メルカリはマイクロサービス 100+ 環境。各サービスがツール選択は自由、ただし lint (Squawk・独自ルール) は共通 CI。Spanner を使うサービスが多いので Spanner CLI + 独自マイグレーションフレームワーク。

メルカリエンジニアリングブログでは「Schema migration as code」コンセプトをよく言及 — Atlas / Bytebase に似た宣言型モデルを社内で実装。

LY Corporation (LINE + Yahoo Japan)

2023 年合併後、LINE コアバックエンドの DB マイグレーションは Flyway 中心に標準化中。一部新規 Go サービスは Atlas。Squawk-MySQL の代替として独自ルールを追加した sql-lint ツール を社内で運用。

共通パターン:

これが 2026 年の韓国・日本ビッグテックの流れ。


結論 — ツールは多く、パターンは少ない

長い記事を一ページに:

  1. ツールは十分にある。 Atlas、Flyway、Liquibase、Sqitch、Bytebase、pgroll、Squawk、gh-ost、pt-osc、Reshape、dbmate、golang-migrate、Diesel、Alembic、Prisma、Drizzle。新しく作る必要はない。
  2. 選択は言語・チーム親和度から始める。 Java なら Flyway、Python なら Alembic、Go なら Atlas / dbmate、TS なら Prisma / Drizzle。
  3. 無停止が必要ならパターンがツールを決める。expand-contract → pgroll (Postgres) / gh-ost (MySQL)。
  4. Squawk (または同等リンタ) はデフォルト。Postgres を使う限り CI に必ず入れる。
  5. ポジティブな down は幻想。 forward-only + 短く安全な変更の連続が reversible より現実的。
  6. マイグレーションツールは安全を保証しない。 expand-contract パターン + lint + レビューが安全。

最後に: 5 分ダウン の原因はツールではなかった。ALTER COLUMN ... SET NOT NULL を 4 億行テーブルに一つのトランザクションで回したパターンが原因。ツールはそのまま、パターンを expand-contract に変えていれば 5 分は 0 秒になっていた。


参考 / References

コメント

まだコメントはありません。

ログインするとコメントできます