データベースの更新が1つ飛ばされて当たった事故と、番号の順番を検査する仕組み

テスト環境で、データベースのマイグレーション(表や列の形を変える更新)の028と029が当たらないまま、030だけが当たりました。原因は、更新の道具が番号の順番を確かめていなかったこと。抜けや順番の崩れを見つけたら何もせずに止まる検査を足した記録です。

「028・029 を飛ばして 030」の文字と、順番の検査の札

マイグレーション(データベースの表や列の形を変える更新)が飛ばされる事故は、当てる前に番号の抜けと順番の崩れを検査し、見つけたら何もせずに止まる作りにすれば防げます。私たちのテスト環境では、028 と 029 が当たらないまま 030 だけが当たり、その原因は、更新の道具が順番を確かめていなかったことでした。

不動産の業務アプリ(Kaitori Base)のテスト環境で、データベースの更新(マイグレーション)が、順番どおりに当たっていないことが分かりました。028 と 029 の更新が当たらないまま、その次の 030 だけが当たっていたのです。

原因は、更新を当てる道具が、番号の順番を確かめていなかったことでした。順番の検査を足し、テスト環境のデータベースは元に戻しました。この記事は、何が起きたかと、再び起きないように足した「順番の検査」の記録です。

マイグレーションは、番号の順に当てるもの

アプリを作り進めると、データベースの形(表や列)を変える必要が出てきます。私たちは、その変更を1つずつファイルにし、先頭に3桁の番号を付けています。番号の順に当てていけば、どの環境でも同じ形のデータベースになります。

データベースの更新(マイグレーション)は、先頭に3桁の番号を付けたファイルを番号の順に当てる。道具はフォルダのファイルの一覧と、当てた記録の2つを見て動く
番号の順に当てれば、どの環境でも同じ形のデータベースになる

更新を当てる道具は、2つのものを見て動きます。

  • 決まったフォルダにある、更新のファイルの一覧
  • データベースに残している、「どのファイルを当てたか」の記録

フォルダにあって、まだ記録に無いファイルを、番号の順に当てていきます。

起きたこと

テスト環境のデータベースを調べると、030は当たっているのに028と029は当たっていなかった。030は前の更新でできた形を前提にしている
前提が欠けたまま、030 が当たっていた

原因は、道具が「フォルダにあるもの」しか見ていなかったこと

更新の道具は、フォルダにあるファイルと、当てた記録しか見ていませんでした。もし、更新を流す時の作業のフォルダに、一部のファイルだけが置かれていたらどうなるでしょう。

引き出しが開いた、古い書類棚の写真
道具は、フォルダの中のものしか見ていなかった(イメージ写真)
更新の番号の図。テスト環境では028と029が当たらず030だけが当たった。後に足した検査は、順番の崩れと番号の抜けを見つけたら何も実行せずに止まる
起きたことと、足した2つの検査

順番の検査を足した

更新の道具に、当てる前の検査を2つ足しました。どちらかに当たったら、何も実行せずに止まります。試しに流すだけの時や、状態を表示するだけの時も、同じ検査をします。

29から33まで、番号が順に並んだ赤い札の写真
番号は、飛ばさず順に当てる(イメージ写真)
当てた記録は027まで、フォルダには030だけがあり、028と029がどこにも無い。この番号の抜けを見つけたら、何も実行せずに止まり、「028・029 が先です」と表示する図
番号の抜けを見つけたら、何も実行せずに止まる
PHP順番の検査(仕組みが分かる短い見本)
// まだ当てていないのに、当てた中で一番新しいものより前の番号がある
$latest = max($appliedNames);
$earlier = array_filter($pendingNames, fn ($n) => strcmp($n, $latest) < 0);

// フォルダにも、当てた記録にも無い番号がある
$known = [];
foreach ([...$appliedNames, ...$fileNames] as $n) {
    $known[(int) substr($n, 0, 3)] = true;
}
$missing = [];
for ($i = min(array_keys($known)); $i <= max(array_keys($known)); $i++) {
    if (!isset($known[$i])) {
        $missing[] = sprintf('%03d', $i);
    }
}

if ($earlier || $missing) {
    exit('マイグレーションは番号の順に、抜かさず当てる必要があります。何も実行していません');
}

止まった時は、どの番号が先に必要かを表示します。「028・029 が先です」のように出るので、何をすればよいかがすぐに分かります。

ターミナルの再現。更新の道具が、番号の順に当てる必要があると表示し、何も実行せずに止まって、028・029が先ですと出している。表示は見本
止まった時の表示のイメージ

本番に当てる時も、新しい道具を使う

本番のサーバーには、検査を足す前の古い道具が残っていました。本番の更新を流す手順では、サーバーの古い道具を使わず、検査の入った新しい道具と、すべての更新のファイルを、一時的な場所に送って使うようにしました。終わったら一時的な場所を消し、道具と接続の情報が残っていないことも確かめます。

本番に更新を当てる時は、サーバーに残っていた古い道具を使わず、検査の入った新しい道具とすべての更新のファイルを一時的な場所に送って使い、終わったら消して接続の情報が残っていないことも確かめる
本番には、検査の入った新しい道具で

まとめ

データベースの更新が1つ飛ばされて当たった事故と、番号の順番を検査する仕組み:要点のまとめ。テスト環境で、028 と 029 を飛ばして 030 だけが当たった
この記事の要点
  • テスト環境で、028 と 029 を飛ばして 030 だけが当たった
  • 道具が、フォルダにあるファイルと当てた記録しか見ず、番号の抜けに気づけなかった
  • 順番の崩れと番号の抜けを見つけたら、何も実行せずに止まる検査を足した
  • 本番でも、検査の入った新しい道具を一時的に送って使う

この記事は、AI(Claude)の支援を受けて作成し、筆者が内容を確認しています。

  • マイグレーション
  • データベース
  • PHP
  • MariaDB
  • テスト環境
  • 事故

関連する記事

この記事に関連するサービス・アプリ

ブログの一覧へ