Skip to content

필사 모드: データベーススキーマ移行 2026 完全ガイド - Atlas (Ariga) · Flyway · Liquibase · Bytebase · dbmate · golang-migrate · Sqitch · Knex · Prisma Migrate 徹底解説

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに — 2026年5月、なぜ今もう一度マイグレーションの話なのか

データベースのスキーマ移行は、十年以上未解決の問題だ。コードは Git でバージョン管理され PR でレビューされるが、スキーマは依然として「誰がいつ何を変えたか」が追いにくい。一行の ALTER TABLE が4時間ロックを握り、サービスを止める。誤ったインデックスが夜間にディスクを埋め、外部キー一つでスレーブのレプリケーションが壊れる。

2026年5月の時点で、この問題は二方向に発展した。一つは **宣言型スキーマツールの台頭** である。Atlas、pgroll、Reshape は最終状態を宣言すると、ツールが diff を作り、安全な順序で適用する。もう一つは **DB ブランチングの普及** だ。Neon、PlanetScale、Supabase、Atlas Cloud がすべての PR に隔離されたプレビュー DB を提供し、移行を実データで検証できるようになった。

この記事は単一の答えを提示しない。代わりに、2026年5月現在の本番で使われているほぼすべてのツールをカテゴリ別に分解し、どのワークロードにどの組み合わせが適しているかを整理する。

マイグレーションが難しい本当の理由

コードデプロイとスキーマ移行は本質的に違う。コードは新しいコンテナを立てトラフィックを移し古いものを落とすだけで済む。スキーマはそうはいかない。

- **状態性**: データベースは状態を持つ。誤った移行はデータ消失である。

- **ロック**: ALTER TABLE はテーブルロックやメタデータロックを取る。10GB テーブルの列追加が4時間かかることもある。

- **互換性**: 旧コードと新コードが同じ DB を同時に見る。単純に列を削るだけで旧コンテナが壊れる。

- **レプリ遅延**: MySQL の非同期レプリや Postgres のストリーミングレプリにとって大きな DDL は重い。

- **ロールバック**: コードは旧イメージに戻せばいい。だが DROP COLUMN の後では列はもう存在しない。

- **マルチリージョン**: 東南アジア、米国、欧州のリージョンで同じスキーマを保証する必要がある。

これらの制約を自動化で吸収するのが 2026 年のマイグレーションツールの目標だ。

一覧 — 2026 年 5 月のツール群

| 区分 | ツール | 主言語 | コアモデル |

| --- | --- | --- | --- |

| 宣言型 | Atlas (Ariga) | Go | HCL/SQL diff |

| 宣言型 | pgroll | Go | Postgres 多段 |

| 宣言型 | Reshape | Rust | Postgres 多段 |

| 命令型 SQL | Flyway 10 | Java | バージョン SQL |

| 命令型 SQL | Liquibase 4.x | Java | XML/YAML changeset |

| 命令型 SQL | dbmate | Go | CLI のみ |

| 命令型 SQL | golang-migrate | Go | ライブラリ + CLI |

| 命令型 SQL | Sqitch | Perl | Git スタイル |

| プラットフォーム | Bytebase | Go | DBA ワークフロー |

| プラットフォーム | Atlas Cloud | Go | SaaS |

| ORM 同梱 | Prisma Migrate | TypeScript | スキーマ → SQL |

| ORM 同梱 | Drizzle Kit | TypeScript | TS → SQL diff |

| ORM 同梱 | TypeORM | TypeScript | デコレータ diff |

| ORM 同梱 | Knex.js | JS | ビルダー移行 |

| ORM 同梱 | Sequelize | JS | モデル diff |

| ORM 同梱 | Alembic | Python | SQLAlchemy diff |

| ORM 同梱 | Django | Python | モデル → 移行 |

| ORM 同梱 | Rails AR | Ruby | DSL DDL |

| ORM 同梱 | Phoenix Ecto | Elixir | DSL DDL |

| ORM 同梱 | Diesel | Rust | SQL up/down |

| ORM 同梱 | GORM | Go | AutoMigrate |

| ORM 同梱 | EF Core | C# | モデル → 移行 |

| オンライン変更 | gh-ost | Go | MySQL トリガレス |

| オンライン変更 | pt-osc | Perl | MySQL トリガ |

この表はマーケティング文言ではなく実際の採用シグナルに基づいている。

Atlas (Ariga.io) — モダンな宣言型と GitOps の路線

Atlas は 2022 年に Ariga が公開したツールで、2026 年 5 月時点で最も急速に成長している移行プラットフォームだ。柱は三つある。

- **宣言型 HCL もしくは SQL**: 望む最終スキーマを宣言すると Atlas が自動で diff を作る。

- **命令型移行もサポート**: 既存の Flyway スタイルのバージョン SQL もそのまま扱える。

- **CI/CD 統合**: GitHub Actions、GitLab CI、CircleCI 用のプラグインがある。PR ごとに視覚的な diff が出る。

Postgres スキーマを HCL で宣言する例は次のとおり。

schema "public" {}

table "users" {

schema = schema.public

column "id" {

type = bigint

null = false

}

column "email" {

type = varchar(255)

null = false

}

column "created_at" {

type = timestamptz

null = false

default = sql("now()")

}

primary_key {

columns = [column.id]

}

index "users_email_idx" {

columns = [column.email]

unique = true

}

}

CLI で diff を作るときの操作は次のようになる。

atlas schema diff \

--from "postgres://user:pass@localhost:5432/app?sslmode=disable" \

--to "file://schema.hcl" \

--dev-url "docker://postgres/15/dev"

atlas migrate diff add_users \

--dir "file://migrations" \

--to "file://schema.hcl" \

--dev-url "docker://postgres/15/dev"

Atlas の核心は **dev-url コンテナ** である。一時コンテナ内ですべての移行を適用したうえで diff を計算するため、ローカル DB の状態に依存しない。さらに `atlas migrate lint` で移行の安全性を静的解析する。たとえば DROP COLUMN、NOT NULL 追加、大規模なバックフィルが発生する変更を PR の段階で警告する。

Atlas Cloud はその SaaS で、ビジュアルなスキーマブラウザ、自動バックフィル、RBAC、監査ログを提供する。

Flyway 10 — JVM エコシステムの事実上の標準

Flyway は 2010 年代から Spring Boot のデフォルトだった。2026 年 5 月時点の 10.x の特徴は次のとおり。

- **SQL ファースト**: V1__create_users.sql、V2__add_email_index.sql のようなバージョン SQL ファイル。

- **Java マイグレーションも可能**: 動的なデータ変換が必要なら Java コードを書く。

- **チェックサム検証**: 既に適用された移行を改ざんすると即失敗する。

- **Flyway Hub**: リモートメタストアとチーム協業。

- **70 以上の DBMS をサポート**: Postgres、MySQL、Oracle、SQL Server、Snowflake、BigQuery など。

典型的な Flyway のワークフローはこうなる。

mkdir -p db/migration

cat > db/migration/V1__create_users.sql <<'SQL'

CREATE TABLE users (

id BIGSERIAL PRIMARY KEY,

email VARCHAR(255) NOT NULL UNIQUE,

created_at TIMESTAMPTZ NOT NULL DEFAULT now()

);

SQL

flyway -url=jdbc:postgresql://localhost:5432/app \

-user=app -password=secret \

-locations=filesystem:db/migration migrate

Flyway 10 の真の強みは **Spring Boot との統合** である。`flyway-core` を依存に入れるだけで起動時に自動的に移行が走る。Java/Kotlin バックエンドではほぼ無条件にこれを選ぶ。

弱点は **宣言型モードがない** こと。常に明示的な ALTER TABLE を書く必要があり、複数環境の同期は別ツールが必要になる。Atlas のような宣言型ツールと併用するチームが増えている。

Liquibase 4.x — XML/YAML 陣営の王者

Liquibase は SQL より一段抽象度の高いモデルを提供する。直接 SQL を書く代わりに changeset という単位で変更を記述する。XML、YAML、JSON、SQL のすべてをサポートする。

databaseChangeLog:

- changeSet:

id: 1

author: youngju

changes:

- createTable:

tableName: users

columns:

- column:

name: id

type: bigint

autoIncrement: true

constraints:

primaryKey: true

- column:

name: email

type: varchar(255)

constraints:

nullable: false

unique: true

- column:

name: created_at

type: timestamptz

defaultValueComputed: NOW()

constraints:

nullable: false

Liquibase の利点は次のとおり。

- **DB 非依存**: 同じ changeset が Postgres、MySQL、Oracle、SQL Server で動く。

- **ロールバック自動生成**: 多くの変更タイプで自動的にロールバック SQL を生成する。

- **Pro 機能**: ポリシーチェック、データ移行、Snowflake/Redshift 統合。

- **Liquibase Hub**: クラウドダッシュボードと変更履歴。

弱点は **冗長性** である。単純な列追加にも YAML を 10 行書く必要がある。4.x では SQL フォーマットの強化が進み、Flyway スタイルに近づきつつある。

Bytebase — DBA + マイグレーションプラットフォーム

Bytebase は 2022 年に公開されたオープンソースの DBA プラットフォームだ。Liquibase や Flyway が「ツール」なら Bytebase は「プラットフォーム」である。主要機能はこうだ。

- **SQL レビュー**: 100 以上のルールセット。NOT NULL 追加のブロック、インデックス不足の警告、大量 UPDATE の検出。

- **PR ベースのワークフロー**: GitHub、GitLab、Bitbucket と連携。SQL ファイルを PR で提出すると自動レビュー。

- **RBAC**: DBA、開発者、リリースマネージャを分離。

- **多段デプロイ**: 開発 → ステージング → 本番のパイプライン。

- **GitOps モード**: Git リポジトリが真実のソース。Bytebase が自動で適用する。

- **AI SQL レビュー**: 2025 年末に GA。生成 AI が危険なパターンを検出し改善案を提示する。

Bytebase は単一バイナリで実行できる。

docker run --rm --init \

--name bytebase \

--publish 8080:8080 \

--volume ~/.bytebase/data:/var/opt/bytebase \

bytebase/bytebase:latest

韓国の Coupang、Toss、NCsoft の DBA チームが Bytebase を導入したという報告がある。日本ではメルカリと LINE ヤフーが内部評価を進めている。

dbmate — 言語非依存の CLI

dbmate は amacneil が作るシンプルな CLI ツールである。Go 製で単一バイナリ。哲学は「ツールは単純であるべき」だ。

- **言語非依存**: Node、Python、Ruby、Go のどこからでも使える。

- **マルチ DB**: Postgres、MySQL、SQLite、ClickHouse。

- **素の SQL ファイル**: -- migrate:up / -- migrate:down のコメントで区切る。

- **状態管理**: 適用履歴は `schema_migrations` テーブル。

dbmate new create_users

db/migrations/20260516120000_create_users.sql を生成

dbmate up

dbmate down

dbmate dump # 現在のスキーマを db/schema.sql に

生成されるファイルはこうなる。

-- migrate:up

CREATE TABLE users (

id BIGSERIAL PRIMARY KEY,

email VARCHAR(255) NOT NULL UNIQUE,

created_at TIMESTAMPTZ NOT NULL DEFAULT now()

);

-- migrate:down

DROP TABLE users;

dbmate は明示的でデバッグしやすい。ORM を使わない Go/Node バックエンドでよく採用される。

golang-migrate — Go の準標準ライブラリ的地位

golang-migrate は Go エコシステムの事実上の標準だ。ライブラリとして組み込むこともできるし、CLI として実行することもできる。

migrate create -ext sql -dir db/migrations -seq create_users

migrate -path db/migrations -database "postgres://localhost:5432/app?sslmode=disable" up

Go コードへの組み込み例。

package main

"github.com/golang-migrate/migrate/v4"

_ "github.com/golang-migrate/migrate/v4/database/postgres"

_ "github.com/golang-migrate/migrate/v4/source/file"

)

func main() {

m, err := migrate.New(

"file://db/migrations",

"postgres://user:pass@localhost:5432/app?sslmode=disable",

)

if err != nil { panic(err) }

if err := m.Up(); err != nil && err != migrate.ErrNoChange {

panic(err)

}

}

golang-migrate は単純だが落とし穴もある。デフォルトでは一度に一つの移行が走り、トランザクションは明示的に扱う必要がある。Postgres 以外ではあまり慣用的でないことがある。

Sqitch — Git スタイル移行のルーツ

Sqitch は Perl 製で、「マイグレーションは Git コミットのように依存関係グラフを持つ」という発想がコアだ。

- **バージョン番号なし**: マイグレーションは名前で識別する。

- **依存関係**: `sqitch add appusers --requires base` のように明示する。

- **`deploy.sql`、`verify.sql`、`revert.sql`**: 三つのファイルが一組。

sqitch init flipr --uri https://github.com/example/flipr --engine pg

sqitch add appusers --requires base -n "Creates appusers schema"

sqitch deploy db:pg://localhost/flipr

sqitch verify db:pg://localhost/flipr

sqitch revert db:pg://localhost/flipr

Sqitch のユーザー数は多くないが、その設計の影響は広い。Atlas のシリアライズモデルも部分的に Sqitch の影響を受けている。

Prisma Migrate 6 — TypeScript 陣営の ORM 同梱型

Prisma は TypeScript バックエンドのデフォルト ORM だ。`schema.prisma` にモデルを宣言すると、`prisma migrate dev` が SQL を生成し適用する。

model User {

id Int @id @default(autoincrement())

email String @unique

createdAt DateTime @default(now()) @map("created_at")

posts Post[]

}

model Post {

id Int @id @default(autoincrement())

title String

authorId Int @map("author_id")

author User @relation(fields: [authorId], references: [id])

}

ワークフローはこうなる。

npx prisma migrate dev --name init

npx prisma migrate deploy # 本番

npx prisma migrate resolve --rolled-back 20260516120000_init

Prisma Migrate 6 の強みは **型安全性と schema.prisma 単一ソース** にある。弱点は次の二つ。

- **水平スケールが弱い**: マルチスキーマやマルチテナントが手薄。

- **複雑な移行は SQL を直接編集**: `prisma migrate diff` で SQL を作り手で整える流れが一般的。

Drizzle Kit — TypeScript ネイティブで SQL 寄りの ORM

Drizzle ORM は 2024 から 2025 にかけて急速に普及した TypeScript ORM だ。Drizzle Kit が移行ツールである。

export const users = pgTable("users", {

id: serial("id").primaryKey(),

email: text("email").notNull().unique(),

createdAt: timestamp("created_at").defaultNow().notNull(),

});

ワークフローはこうだ。

npx drizzle-kit generate # TS スキーマ diff → SQL

npx drizzle-kit migrate # 適用

npx drizzle-kit studio # 可視化

Drizzle Kit は Prisma より **SQL に近い**。生成される SQL が読みやすく、手で編集しても次の generate で保持される。サーバーレスやエッジ環境(Cloudflare Workers、Vercel Edge)で特に強い。

Knex.js — ビルダー + マイグレーション

Knex.js は SQL クエリビルダだが、独自のマイグレーション機能も持つ。Express/Fastify 系で ORM を使わずに進めるチームがよく採用する。

exports.up = async function(knex) {

await knex.schema.createTable("users", (t) => {

t.bigIncrements("id").primary();

t.string("email", 255).notNullable().unique();

t.timestamp("created_at").notNullable().defaultTo(knex.fn.now());

});

};

exports.down = async function(knex) {

await knex.schema.dropTable("users");

};

Knex マイグレーションの強みは **DB 非依存のビルダ** である。同じコードが Postgres、MySQL、SQLite、MS SQL Server で動く。弱点は抽象化の漏れだ。DB 固有機能を使いたければ結局 `knex.raw()` に落とす。

Sequelize CLI — JS ORM の古参

Sequelize は Node.js のクラシック ORM だ。Sequelize CLI が移行を担う。

npx sequelize-cli migration:generate --name create-users

生成されるファイルは `up`、`down` の二関数構成。

"use strict";

module.exports = {

up: async (queryInterface, Sequelize) => {

await queryInterface.createTable("Users", {

id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true },

email: { type: Sequelize.STRING(255), allowNull: false, unique: true },

createdAt: { type: Sequelize.DATE, allowNull: false },

updatedAt: { type: Sequelize.DATE, allowNull: false },

});

},

down: async (queryInterface) => {

await queryInterface.dropTable("Users");

},

};

Sequelize は新規導入先としては勢いがないが、レガシーコードベースには広く根付いている。

Alembic — Python SQLAlchemy 陣営の標準

Alembic は SQLAlchemy の作者 Mike Bayer が作った移行ツールで、Django 以外の Python バックエンドの事実上の標準である。

alembic init alembic

alembic revision --autogenerate -m "create users"

alembic upgrade head

alembic downgrade -1

生成される移行スクリプトはこうなる。

from alembic import op

revision = "1a2b3c4d5e6f"

down_revision = None

def upgrade() -> None:

op.create_table(

"users",

sa.Column("id", sa.BigInteger, primary_key=True),

sa.Column("email", sa.String(255), nullable=False),

sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),

sa.UniqueConstraint("email", name="users_email_key"),

)

def downgrade() -> None:

op.drop_table("users")

Alembic の `--autogenerate` は SQLAlchemy モデルと DB を比較して diff を作る。強力だが完全ではないので、生成されたスクリプトは必ずレビューする。FastAPI + SQLAlchemy ではほぼ Alembic 一択だ。

Django Migrations — モデルから自動生成

Django は ORM と移行が完全に統合されている。`models.py` を編集して `makemigrations` を実行すれば移行ファイルが生成され、`migrate` で適用する。

from django.db import models

class User(models.Model):

email = models.EmailField(unique=True)

created_at = models.DateTimeField(auto_now_add=True)

python manage.py makemigrations

python manage.py migrate

python manage.py migrate --plan # 適用予定の変更をプレビュー

python manage.py sqlmigrate myapp 0001 # SQL を表示

Django マイグレーションは強力だが罠もある。

- **RunPython**: データ移行は明示的に書く。

- **AtomicMigration**: Postgres ではトランザクション内で DDL を実行する。巨大なバックフィルは `atomic = False` を指定する。

- **squashmigrations**: 蓄積した移行を圧縮する。

Django ショップではほぼ 100% Django Migrations を使う。Alembic を併用するのは稀である。

Rails Active Record Migrations — 最も影響力のあるマイグレーション DSL

Rails は 2005 年から移行 DSL の標準を作ってきた。以後ほぼすべてのツールが影響を受けている。

class CreateUsers < ActiveRecord::Migration[7.1]

def change

create_table :users do |t|

t.string :email, null: false

t.timestamps

end

add_index :users, :email, unique: true

end

end

rails generate migration CreateUsers email:string

rails db:migrate

rails db:rollback STEP=1

強みは **`change` メソッド** で、一度書けば up と down が自動で推論される。弱点は強いコンベンションで、非標準の変更は `up`、`down` を明示する必要がある。

Phoenix Ecto Migrations — Elixir の関数型 DSL

Elixir/Phoenix 陣営は Ecto を使う。Ecto.Migration は Rails AR に似た DSL を提供する。

defmodule MyApp.Repo.Migrations.CreateUsers do

use Ecto.Migration

def change do

create table(:users) do

add :email, :string, null: false

timestamps()

end

create unique_index(:users, [:email])

end

end

mix ecto.gen.migration create_users

mix ecto.migrate

mix ecto.rollback

BEAM ランタイムと Elixir の関数型スタイルのおかげで、移行コードが特にクリーンに保てる。マルチテナントは Repo の動的設定で扱う。

Diesel Migrations — Rust 陣営のコンパイル時マイグレーション

Diesel は Rust の ORM 兼クエリビルダだ。移行ツールも同梱される。

diesel migration generate create_users

migrations/<timestamp>_create_users/{up.sql,down.sql} を生成

diesel migration run

diesel migration revert

-- up.sql

CREATE TABLE users (

id BIGSERIAL PRIMARY KEY,

email VARCHAR(255) NOT NULL UNIQUE,

created_at TIMESTAMPTZ NOT NULL DEFAULT now()

);

-- down.sql

DROP TABLE users;

Diesel はコンパイル時にスキーマとクエリを検証することに重きを置く。`diesel print-schema` が Rust 型を自動生成し、その型とクエリが合わなければコンパイルで失敗する。

Sea-ORM は Diesel の代替で、非同期ファーストで移行 DSL は Rust コードで書く。

use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]

pub struct Migration;

#[async_trait::async_trait]

impl MigrationTrait for Migration {

async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {

manager.create_table(Table::create()

.table(Users::Table)

.col(ColumnDef::new(Users::Id).big_integer().not_null().auto_increment().primary_key())

.col(ColumnDef::new(Users::Email).string().not_null().unique_key())

.to_owned()).await

}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {

manager.drop_table(Table::drop().table(Users::Table).to_owned()).await

}

}

EF Core Migrations — .NET の標準

Entity Framework Core は .NET エコシステムのデフォルト ORM だ。移行は dotnet ef CLI で管理する。

dotnet ef migrations add CreateUsers

dotnet ef database update

dotnet ef migrations script

dotnet ef migrations remove

生成される移行は C# コードである。

public partial class CreateUsers : Migration

{

protected override void Up(MigrationBuilder migrationBuilder)

{

migrationBuilder.CreateTable(

name: "Users",

columns: table => new

{

Id = table.Column<long>(nullable: false).Annotation("SqlServer:Identity", "1, 1"),

Email = table.Column<string>(maxLength: 255, nullable: false),

CreatedAt = table.Column<DateTime>(nullable: false, defaultValueSql: "GETUTCDATE()")

},

constraints: table =>

{

table.PrimaryKey("PK_Users", x => x.Id);

table.UniqueConstraint("UQ_Users_Email", x => x.Email);

});

}

protected override void Down(MigrationBuilder migrationBuilder)

{

migrationBuilder.DropTable(name: "Users");

}

}

EF Core は SQL Server 以外に Postgres(Npgsql)、MySQL(Pomelo)、SQLite もよくサポートする。

GORM AutoMigrate — Go ORM の自動モード

Go の GORM は `AutoMigrate` というシンプルな API を提供する。

type User struct {

ID uint `gorm:"primarykey"`

Email string `gorm:"uniqueIndex;size:255;not null"`

CreatedAt time.Time

}

db.AutoMigrate(&User{})

`AutoMigrate` は速いが **抜けが多い**。列の削除や型変更を安全には行わない。そのため GORM ユーザーも本番では golang-migrate や Atlas と組み合わせて使う。

オンラインスキーマ変更 — gh-ost、pt-online-schema-change、pgroll、Reshape

大きなテーブルに対する ALTER TABLE はロック爆弾だ。これを回避するツールがいくつかある。

**gh-ost** (GitHub Online Schema Transmogrifier) は GitHub が作った MySQL 用のツールである。トリガを使わず binlog を追従しシャドーテーブルを作る。

gh-ost \

--max-load=Threads_running=25 \

--critical-load=Threads_running=1000 \

--chunk-size=1000 \

--max-lag-millis=1500 \

--user="ghost" --password="secret" \

--host=replica.example.com \

--database="myapp" \

--table="users" \

--alter="ADD COLUMN nickname VARCHAR(64)" \

--switch-to-rbr --allow-master-master --cut-over=default \

--exact-rowcount --concurrent-rowcount --default-retries=120 \

--panic-flag-file=/tmp/ghost.panic.flag \

--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \

--execute

**pt-online-schema-change** (Percona Toolkit) はトリガベースだが十年以上の運用実績がある。

pt-online-schema-change \

--alter "ADD COLUMN nickname VARCHAR(64)" \

D=myapp,t=users \

--execute

**pgroll** (Xata) は Postgres 用の無停止スキーマ変更ツール。同じスキーマを二つのバージョンで同時に公開(ビュー経由)し、段階的にトラフィックを切り替えられる。

pgroll start migrations/001_add_nickname.json

pgroll complete # トラフィック切替後に古い列を片付ける

pgroll rollback # 問題があれば前バージョンに戻す

**Reshape** は pgroll と同様の発想の Rust 製ツールだ。どちらも Expand-Contract パターンを道具化したものである。

**pg_repack** は移行ツールではないが、ALTER 後に断片化したテーブル/インデックスをロックなしで再構築する。

Expand-Contract — 無停止移行のデフォルトパターン

ほとんどの無停止移行は Expand-Contract パターンに従う。

1. **Expand**: 新しい列やテーブルを追加する。旧コードも新コードも動く。

2. **Backfill**: 旧列から新列へバッチでデータをコピー。

3. **Dual write**: 新コードが両方に書く。段階的にロールアウト。

4. **Read switch**: 読みを新列へ切り替える。カナリアで広げる。

5. **Contract**: 旧列を削除する。

コードデプロイは一段だが、スキーマ変更は五段に分解する必要がある。pgroll、Reshape、Atlas Cloud のコアバリューはこのパターンを自動化することにある。

DB ブランチング — Neon、PlanetScale、Supabase、Atlas Cloud

2025 年以降 DB ブランチングが普及した。PR ごとに隔離されたブランチが作られ、移行が実データで検証される。

- **Neon**: Postgres の Copy-on-Write ブランチ。数秒で新ブランチを作れる。

- **PlanetScale**: MySQL/Vitess ベース。ブランチはスキーマ変更の単位。

- **Supabase Branching**: PR 単位のプレビュー DB。移行は自動適用される。

- **Atlas Cloud**: Atlas で管理されている任意の DB にブランチプレビュー。

ブランチ DB は移行の安全性検証で最も強力な手段だ。本番データの匿名化コピーで移行を事前に走らせてからマージする運用が事実上の標準になっている。

スキーマ可視化 — dbdiagram.io、DrawSQL、Mermaid ER

スキーマは可視化されたとき最も価値が伝わる。2026 年 5 月時点の主要ツール。

- **dbdiagram.io**: DBML というテキスト DSL で ER 図を作る。

- **DrawSQL**: 共同編集できる ER デザイナ。

- **Mermaid erDiagram**: GitHub README にそのまま埋め込める。

- **DBeaver、DataGrip**: IDE 級クライアントが自動で ER を生成。

- **SchemaSpy**: 静的 HTML としてスキーマドキュメントを生成。

- **DBdocs**: dbdiagram のドキュメントホスティング。

- **eraser.io**: 図とノートとマークダウンの協業ツール。

これらは移行を直接適用するわけではないが、PR レビュー時の前後比較に役立つ。

移行テスト — testcontainers、schemathesis

移行もテスト対象だ。2026 年 5 月の標準ツール群はこうなる。

- **testcontainers**: 統合テストごとに本物の Postgres/MySQL コンテナを立てる。移行を適用してクエリを試す。

- **schemathesis**: OpenAPI スキーマから自動生成されたテストで API + DB 一貫性を検証する。

- **Atlas migrate lint**: 移行の静的安全性解析。

- **Bytebase SQL Review**: 100 以上のルールセットによる静的検査。

Go で testcontainers を使う例。

ctx := context.Background()

pgC, err := postgres.RunContainer(ctx,

testcontainers.WithImage("postgres:15-alpine"),

postgres.WithDatabase("test"),

postgres.WithUsername("test"),

postgres.WithPassword("test"),

)

defer pgC.Terminate(ctx)

dsn, _ := pgC.ConnectionString(ctx, "sslmode=disable")

m, _ := migrate.New("file://./migrations", dsn)

require.NoError(t, m.Up())

マルチ DB 移行 — Postgres / MySQL / SQLite / MS SQL Server

複数 DB を同時に支える場合、ツールごとの互換性が重要になる。

| ツール | Postgres | MySQL | SQLite | MS SQL | Oracle |

| --- | --- | --- | --- | --- | --- |

| Atlas | full | full | full | Cloud のみ | partial |

| Flyway 10 | full | full | full | full | full |

| Liquibase 4.x | full | full | full | full | full |

| Bytebase | full | full | full | full | full |

| dbmate | full | full | full | partial | no |

| golang-migrate | full | full | full | full | full |

| Prisma | full | full | full | full | partial |

| Alembic | full | full | full | full | full |

DB 非依存の抽象が強いほど DB 固有機能の露出が弱くなる。Postgres 固有機能(`GENERATED ALWAYS AS`、パーティショニング、BRIN インデックス)を使うには結局 raw SQL に落ちることが多い。

CI/CD 統合 — GitHub Actions、GitLab CI、ArgoCD

移行は CI/CD パイプラインの一級市民であるべきだ。

GitHub Actions に Atlas を組み込む例。

name: Migrate

on:

push:

branches: [main]

jobs:

migrate:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- uses: ariga/setup-atlas@v0

- run: |

atlas migrate apply \

--dir "file://migrations" \

--url "${{ secrets.DATABASE_URL }}" \

--tx-mode all

ArgoCD Hook として Flyway を回すパターンもよく見る。新コンテナのデプロイ前に PreSync Hook で移行を適用する。

apiVersion: batch/v1

kind: Job

metadata:

name: flyway-migrate

annotations:

argocd.argoproj.io/hook: PreSync

argocd.argoproj.io/hook-delete-policy: HookSucceeded

spec:

template:

spec:

restartPolicy: Never

containers:

- name: flyway

image: flyway/flyway:10

args: ["migrate"]

envFrom:

- secretRef:

name: flyway-config

AI を組み込んだ移行 — Bytebase Copilot、Atlas Copilot

2025 年以降、移行ツールにも AI 機能が組み込まれ始めた。

- **Bytebase SQL Review AI**: 生成 AI が移行の危険パターンを日本語/英語で説明。

- **Atlas Copilot**: 自然言語の要件から HCL スキーマを生成し、SQL diff を自然言語で説明。

- **CodeRabbit、Greptile**: PR レビュー時に移行の安全性チェックを統合。

AI は二つの場所で価値を生む。一つは **危険シグナルの自然言語説明** で、「この ALTER は 1 億行のテーブルで 4 時間ロックを取る可能性があります」と教えてくれる。もう一つは **移行パターンの推奨** で、Expand-Contract への分解を促すリファクタ提案だ。

韓国の事例 — NCsoft、Coupang、NAVER

韓国の IT 企業の DBA チーム事例には次の傾向が見える。

- **NCsoft**: ゲームバックエンドの MySQL クラスタで gh-ost を広く運用。

- **Coupang**: マイクロサービスごとに Flyway か Liquibase。社内 PR ワークフローに Bytebase の評価報告。

- **NAVER**: 大規模 MySQL/MyRocks 環境で独自 DBA ツール + pt-online-schema-change を併用。

- **Kakao**: Postgres + Liquibase ワークフロー。一部チームは Atlas を評価段階。

- **Toss**: 社内 RDS 運用チームが自作 GitOps パイプラインと Flyway を組み合わせる。

全体として、Bytebase のような韓国語対応 SaaS への導入は日本より積極的な流れがある。

日本の事例 — メルカリ、LINE ヤフー、サイバーエージェント、DeNA

日本の大規模サービス運用者の傾向はこうだ。

- **メルカリ**: Atlas と golang-migrate の評価/導入報告。メインバックエンドは Go。

- **LINE ヤフー**: 統合後、複数の移行ツールが並行して使われる。Flyway、Liquibase、golang-migrate が混在。

- **サイバーエージェント**: ゲームバックエンドの MySQL で gh-ost を広く運用。

- **DeNA**: Mobage 時代から続く大規模 MySQL 運用。gh-ost と自作ツールの組み合わせ。

- **SmartHR**: Rails + ActiveRecord Migrations が標準。一部 Liquibase もあり。

日本は Go エコシステムと MySQL 運用ノウハウが強く、gh-ost のようなツールの採用が速い。

ツールの推奨組み合わせ — ワークロード別の最適解

最後にワークロード別の推奨組み合わせを置く。

- **Spring Boot + 単一 Postgres/MySQL**: Flyway 10。代替はほぼない。

- **Go バックエンド + 複数 DB**: 宣言型の Atlas をフロントに、エンジンは golang-migrate。

- **TypeScript + サーバーレス/エッジ**: Drizzle Kit。

- **TypeScript + 伝統的バックエンド**: Prisma Migrate 6 か Drizzle Kit。

- **Python FastAPI**: Alembic。

- **Django**: Django Migrations。必要に応じて pgroll。

- **Rails**: Active Record Migrations。

- **.NET**: EF Core Migrations。

- **大規模 MySQL**: 上記 + gh-ost。

- **大規模 Postgres**: 上記 + pgroll もしくは Reshape。

- **複数チーム、強いガバナンスが必要**: Bytebase をプラットフォームとして導入。

- **強い GitOps ワークフロー**: Atlas Cloud + GitHub Actions。

おわりに — ツールは分岐し、パターンは収束する

2026 年 5 月の時点で移行ツールは生態系ごとに分岐した。JVM は Flyway、.NET は EF Core、Python は Alembic + Django、TypeScript は Prisma/Drizzle、Go は golang-migrate/Atlas で固まりつつある。

しかしパターンは収束する。どのツールを選んでも以下の原則は当てはまる。

1. **すべての変更は PR とコードレビューを通る。**

2. **移行は自動化された CI で検証される。**

3. **大きな変更は Expand-Contract に分解する。**

4. **オンラインスキーマ変更ツールでロック起因の停止を避ける。**

5. **ロールバック計画を移行と一緒に書く。**

6. **DB ブランチで実データに対して検証する。**

ツールはこれらの原則をより安価に満たすための手段である。自分のワークロードとチームに合うツールを選びながらも、原則は動かさないことが大切だ。

参考資料

1. [Atlas 公式ドキュメント (Ariga.io)](https://atlasgo.io/)

2. [Atlas GitHub](https://github.com/ariga/atlas)

3. [Flyway 公式ドキュメント](https://flywaydb.org/documentation/)

4. [Flyway GitHub](https://github.com/flyway/flyway)

5. [Liquibase 公式ドキュメント](https://docs.liquibase.com/)

6. [Liquibase GitHub](https://github.com/liquibase/liquibase)

7. [Bytebase 公式ドキュメント](https://www.bytebase.com/docs/)

8. [Bytebase GitHub](https://github.com/bytebase/bytebase)

9. [dbmate GitHub](https://github.com/amacneil/dbmate)

10. [golang-migrate GitHub](https://github.com/golang-migrate/migrate)

11. [Sqitch 公式サイト](https://sqitch.org/)

12. [Prisma Migrate 公式ドキュメント](https://www.prisma.io/docs/orm/prisma-migrate)

13. [Drizzle Kit 公式ドキュメント](https://orm.drizzle.team/kit-docs/overview)

14. [TypeORM Migrations ドキュメント](https://typeorm.io/migrations)

15. [Knex.js Migrations ドキュメント](https://knexjs.org/guide/migrations.html)

16. [Sequelize CLI ドキュメント](https://github.com/sequelize/cli)

17. [Alembic 公式ドキュメント](https://alembic.sqlalchemy.org/)

18. [Django Migrations ドキュメント](https://docs.djangoproject.com/en/stable/topics/migrations/)

19. [Rails Active Record Migrations ガイド](https://guides.rubyonrails.org/active_record_migrations.html)

20. [Phoenix Ecto Migrations ドキュメント](https://hexdocs.pm/ecto_sql/Ecto.Migration.html)

21. [Diesel Migrations ドキュメント](https://diesel.rs/guides/getting-started)

22. [Sea-ORM Migrate ドキュメント](https://www.sea-ql.org/SeaORM/docs/migration/setting-up-migration/)

23. [EF Core Migrations ドキュメント](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/)

24. [GORM AutoMigrate ドキュメント](https://gorm.io/docs/migration.html)

25. [gh-ost GitHub](https://github.com/github/gh-ost)

26. [pt-online-schema-change ドキュメント](https://docs.percona.com/percona-toolkit/pt-online-schema-change.html)

27. [pgroll GitHub (Xata)](https://github.com/xataio/pgroll)

28. [Reshape GitHub](https://github.com/fabianlindfors/reshape)

29. [pg_repack GitHub](https://github.com/reorg/pg_repack)

30. [Neon Branching ドキュメント](https://neon.tech/docs/introduction/branching)

31. [PlanetScale Branching ドキュメント](https://planetscale.com/docs/concepts/branching)

32. [Supabase Branching ドキュメント](https://supabase.com/docs/guides/platform/branching)

33. [dbdiagram.io](https://dbdiagram.io/)

34. [DrawSQL](https://drawsql.app/)

35. [Mermaid erDiagram ドキュメント](https://mermaid.js.org/syntax/entityRelationshipDiagram.html)

36. [SchemaSpy](https://schemaspy.org/)

37. [testcontainers Go](https://golang.testcontainers.org/)

38. [schemathesis ドキュメント](https://schemathesis.readthedocs.io/)

현재 단락 (1/578)

データベースのスキーマ移行は、十年以上未解決の問題だ。コードは Git でバージョン管理され PR でレビューされるが、スキーマは依然として「誰がいつ何を変えたか」が追いにくい。一行の ALTER T...

작성 글자: 0원문 글자: 22,408작성 단락: 0/578