db-migration-safety について
db-migration-safetyは、実行前のSQLやORMマイグレーションファイルを静的に検査するスキルで、監査役や作成エージェントが利用します。ロールバック、ロック、テーブル再書き換え、破壊的操作、スキーマドリフトを確認し、実行せずに修正案を提示します。
主な機能
- 01ロールバックと拡張・縮小手順を確認
- 02ブロッキングロックとテーブル再書き換えを検出
- 03破壊的操作とNOT NULLの問題を検出
- 04列挙型の変更とスキーマドリフトを確認
- 05安全な書き換えと検証方法を提示
活用シーン
- 01実行前のデータベースマイグレーション確認
- 02高負荷テーブルをブロックするSQLの発見
- 03新しいNOT NULL列のバックフィル計画
- 04マイグレーション履歴とスキーマ定義の照合
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hainrixz/ claude-db --skill db-migration-safetyインストール後、Claude Code で/db-migration-safetyを入力して読み込まれたか確認します。
詳細
db-migration-safety (M22) — マイグレーションの lint 契約
M22 は、候補となるマイグレーションを実行前に静的アーティファクトとして lint します。これは、migration-safety auditor と db-migration-writer エージェントの両方が遵守する契約です。Performance & Scale(Almacenamiento/運用性カテゴリ)に情報を提供します。破壊的でロールバック不能なマイグレーションは、パフォーマンス軸で sev-5 の上限となります。
チェック内容(lint 契約)
- 可逆性 — 使用可能な
down/ロールバックがあるか、変更が expand-contract(別々のデプロイでの add-new → backfill → switch → drop-old)に従っているかを確認します。downのない一度限りの破壊的ステップは、ここで最も重大度の高い指摘となります。 - ロックレベル — ステートメントがホットテーブルに書き込みをブロックするロックを取得するかを確認します。Postgres では、揮発性デフォルト値を伴う列の追加(11 未満)、
ALTER COLUMN TYPE、NOT VALIDを指定しないCHECK/FK の追加、CONCURRENTLYを指定しないインデックス作成は、いずれもACCESS EXCLUSIVEを取得するか、書き込みをブロックします。CREATE INDEX CONCURRENTLY、ADD CONSTRAINT ... NOT VALIDの後にVALIDATE CONSTRAINTを使用してください。 - テーブルの書き換え — テーブル全体の書き換えを引き起こす変更(特定の
ALTER COLUMN TYPE、古いエンジンで揮発性デフォルト値を伴うNOT NULL列の追加など)は、大きなテーブルでは処理が遅く、ロックが長時間続きます。 - 破壊的操作 —
DROP COLUMN、DROP TABLE、TRUNCATE、DROP NOT NULLのロールバック、デプロイ済みコードがまだ読み取っている列の削除。破壊的かつロールバック不能な操作は sev 5 となり、パフォーマンスの上限を定めます。 - デフォルト値なしの NOT NULL — データが入っているテーブルに
NOT NULLをデフォルト値なしで追加すると、失敗するかロックが発生します。バックフィル計画が必要です。 - Enum の変更 — 長期的な懸念事項は、enum 値を削除も並べ替えもできないことです(削除はサポートされておらず、名前変更や並べ替えは依存するものを破損させます)。値の集合が変わる場合は、ネイティブ enum ではなくルックアップテーブルを使用してください。
ALTER TYPE ... ADD VALUEは追加のみで、PG12 以降ではトランザクション内で実行できます(トランザクション中の実行が禁止されていたのは古い PG のみです)。enum の変更を検出し、ルックアップテーブルを提案します。 - スキーマのドリフト — 宣言的アーティファクト(schema.prisma / structure.sql / snapshot)とマイグレーション履歴が一致しない(列が一方には存在するが、もう一方には存在しない)場合は、方向性を示す警告を出します。
Tier-0 静的チェック
マイグレーション SQL/ORM マイグレーションファイル(scripts/parse-schema.mjs、parse-orm-python.py)を解析します。次の項目をスキャンします。
DROP TABLE|DROP COLUMN|TRUNCATE;ALTER COLUMN .* TYPE;DEFAULT のない ADD COLUMN .* NOT NULL;CONCURRENTLY を指定していない CREATE INDEX;NOT VALID を指定していない ADD CONSTRAINT(FK/CHECK);ALTER TYPE .* ADD VALUE/enum 値の削除や並べ替え;down/ロールバックブロックの欠如;正本となるアーティファクト(優先順位は references/detection-signals.md)と最新のマイグレーションとのドリフト。
Tier-1 検証クエリ
- 影響を受けるテーブルのサイズ(ロックが問題になるか):
SELECT pg_size_pretty(pg_total_relation_size('<t>')), reltuples FROM pg_class WHERE relname='<t>'; - ステートメントが取得するロック:
EXPLAIN/pg_locksの調査、または使い捨てコピー/シャドウ DB に対するdry_run_migration。シャドウ DB が利用可能な場合はverification.method: dry_run_migrationを使用し、利用できない場合は静的 SQL に対してmigration_lintを実行します。重大度の判断にライブ環境のサイズが必要なのに DB に接続できない場合は、黙って合格とせず、needs_apiとします。
検出結果
schema/finding.schema.json に従って出力します。ID の例:
M22.20240115_drop_users_legacy.destructive_irreversible— down がなく、列がまだ参照されている状態でのDROP COLUMN(失敗、重大度 5、軸performance、修正可能性proposed→ expand-contract プラン)。M22.add_index.lock_blocking— ホットテーブルでのCONCURRENTLYを使わないCREATE INDEX(警告、重大度 4、軸performance、修正可能性auto→CONCURRENTLYを追加)。M22.add_email_notnull.notnull_no_default— データが格納済みのテーブルで、デフォルト値なしのADD COLUMN ... NOT NULL(失敗、重大度 4、軸performance、修正可能性proposed)。M22.status_enum.enum_value_removed— enum 値の削除/順序変更(未サポート。依存先を破壊します)— ルックアップテーブルを提案(警告、重大度 3、軸performance)。M22.drift.column_in_artifact_not_migration— スキーマドリフト(警告、重大度 2、軸performance、信頼度directional)。 各検出結果では、evidence.observedに問題のあるマイグレーション文をそのまま引用します(シークレットは墨消し)。verification.reproduceは上記の$DATABASE_URLを使った実行可能なコマンドです。verification.methodはmigration_lintまたはdry_run_migrationです。fix_previewには、より安全な書き換え(例:CONCURRENTLY、NOT VALID+VALIDATE、expand-contract の一連の手順)が含まれます。expected_impactには{axis, confidence, magnitude, rationale}が含まれ、影響度は必ず段階で示し、単独の % は使用しません。
誠実さ
- ロックの重大度はテーブルのサイズと書き込み頻度によって異なります。実環境の証拠がない場合、サイズ不明のテーブルに対するブロッキング操作は、確定した重大度 5 ではなく
directional(中程度)です。停止時間を秒単位で断定してはいけません。影響度は段階でのみ示します。 DROP/TRUNCATEクラスの破壊的かつ不可逆なマイグレーションのみ、パフォーマンスの重大度を 5 に制限します。可逆な変更や expand-contract 方式の変更は警告です。ドリフトは方向性のあるものとして扱い、重大度の上限には影響しません。- 読み取り専用です。M22 は lint と提案を行いますが、マイグレーションは実行しません。実行は、ユーザーが明示的に承認したうえで、書き込みエージェントが担当します。