マイグレーションPRを10分でレビューするチェックリスト
マイグレーションのレビューで一番危ないのは、SQLが「読める」ことだ。読めるから、つい目で追って承認してしまう。だが本番を壊すパターンの大半は、目で追うには地味すぎる。だからレビューは、読む作業ではなく照合する作業にした方がいい。以下は、PRを開いたら10分で照合する順番だ。
0分〜2分: まず「破壊的か」を分ける
最初に確認するのは、変更が次のどれに当たるかだけだ。
- カラムの削除・リネーム
- NOT NULL の追加
- 型の縮小(例:
TEXT→VARCHAR(255)、数値の桁下げ) - テーブル削除、
TRUNCATE - 既存行に影響する
UPDATE/DELETE
どれか一つでも当たれば、そのPRは「通常のPR」ではない。展開と縮小(expand–contract)を分けた手順になっているか、ロールバック手順が書かれているかを、まず確認する。手順が書かれていない破壊的変更は、SQLの正しさ以前にレビューを止める理由になる。
2分〜5分: 5つの定番パターンを照合する
前回の記事で取り上げた5パターンを、PRの差分にそのまま当てはめる。
-
リネームが
DROP COLUMN+ADD COLUMNになっていないか。 値が消える。安全なのは、追加 → バックフィル → 切替 → 削除の4段階。 - NOT NULL に DEFAULT がないか。 既存行があるテーブルではそのまま失敗するか、テーブル全体の書き換えになる。nullableで追加してからバックフィルし、最後に制約を付ける。
-
CREATE INDEXがCONCURRENTLYなしでないか。 Postgresでは書き込みが止まる。CONCURRENTLYを使う場合は、トランザクション外で実行することと、失敗時に残るINVALIDなインデックスの扱いも確認する。 -
SET NOT NULLが素のまま入っていないか。 Postgres 12以降なら、まずCHECK (...) NOT VALIDを付けてVALIDATE CONSTRAINTし、最後にSET NOT NULLする手順でロックを短くできる。 - DDLとDMLが同じファイルに混ざっていないか。 途中で死んだとき、どこまで進んだか分からなくなる。スキーマ変更、データ移行、縮小は別ファイルに分ける。
この5つは判断ではなく照合だ。機械が先に拾って、人間は「本当にこの手順でいいか」だけを判断するのが筋がいい。
5分〜8分: アプリケーション側の参照を確認する
SQLだけ見て承認してはいけない。次を確認する。
- 削除・リネーム対象のカラムを、まだ参照しているコードはないか(Prismaのスキーマ、Djangoのモデル、Alembicの後続マイグレーション、生SQL)。
- ローリングデプロイ中に旧コードと新コードが両方動く期間があるか。その期間に、旧コードが読むカラム・新コードが書くカラムは両方存在するか。
- バックフィルは冪等か、再実行できる範囲指定になっているか。夜中に失敗して「もう一度回すだけ」で済む形になっているか。
ここで引っかかるのは、SQLのバグではなく「デプロイ順序の思い込み」であることが多い。
8分〜10分: ロールバックを一文で言えるか
最後に、自分でこう言えるか試す。「このマイグレーションが失敗したら、○○を××することで戻せる」。言えないなら、PRにロールバック手順を書いてもらう。戻し方が書かれていない破壊的変更は、デプロイではなく賭けだ。
機械に任せる部分と、人間がやる部分
上のチェックリストのうち、5パターンの検出と参照の洗い出しは、テキストのパターンとして機械化できる。私が公開している無料のクイックスキャンは、その最初の10パターンを標準ライブラリのみのPythonでチェックする(データベースには接続しない)。
フル版の監査スキルは、Prisma・Django・Alembicへの対応、アプリケーションコードとの突き合わせ、マイグレーションごとの GO / NEEDS EXPAND-CONTRACT / NO-GO 判定、expand–contract の書き換え案、ロールバック計画まで含む。PromptBaseで公開中だ。
- Zero-Downtime DB Migration Auditor: https://promptbase.com/skill/zerodowntime-db-migration-auditor-2
マイグレーションのレビューは、速くすることが目的ではない。10分で「止めるべき理由がない」ことを確認できれば、それで十分だ。止める理由が一つでも見つかれば、その10分は本番障害の何時間分にもなる。
Top comments (0)