本番環境を壊さないマイグレーション

マイグレーションは、ローカル環境では完璧に動作します。小規模な変更に見えるため、金曜日の午後6時にデプロイします。すると、デプロイがフリーズします。あるいはさらに悪いことに、800万行あるテーブルが40秒間ロックされ、サイトがダウンしてしまいます。

マイグレーションの挙動は、本番環境では異なります。ローカルのデータベースは空で高速ですが、本番環境のデータベースには実際のデータとアクティブなユーザーが存在します。

本番環境での災難を避けるために、以下のルールに従ってください。

  • 常に動作する down メソッドを書く すべてのマイグレーションには up 関数と down 関数が必要です。down 関数は up 関数を正確に逆転させるものでなければなりません。ロールバックが書けないのであれば、そのマイグレーションは複雑すぎます。プッシュする前に、ローカル環境で migrate を実行した後に migrate:rollback を実行してテストしてください。

  • 過去のマイグレーションを編集しない 過去のマイグレーションファイルでカラムのサイズを修正したくなるかもしれません。しかし、それはしないでください。Laravelはサーバー上でそのファイルを再度実行することはありません。代わりに、構造を変更するための新しいマイグレーションを作成してください。マイグレーションは変更の履歴です。古い章を書き換えるのではなく、新しい章を追加していくのです。

  • nullable またはデフォルト値を使用する すでにデータが存在するテーブルに NOT NULL カラムを追加すると、エラーが発生します。データベースは既存の行に何を入れればよいかわからないからです。

代わりに、以下の方法をとってください: • 新しいカラムを nullable にする。 • デフォルト値を設定する。 • カラムを必須にする必要がある場合は、3つのステップで行います:まず nullable として作成し、データを入力した後、NOT NULL に変更します。

  • データ損失は取り返しがつかない dropColumn コマンドはデータを永久に削除します。ロールバックによってカラムを再作成することはできますが、中のデータは失われたままです。カラムを削除する前に、バックアップを確認してください。より安全な方法は、まずコード内でのカラムの使用を停止し、数週間待ってからデータベースから削除することです。

  • スキーマ変更とデータ更新を分離する マイグレーション内で User::all() を実行すると、数百万行がメモリに読み込まれ、デプロイがクラッシュする可能性があります。マイグレーション中にデータを更新する必要がある場合は、chunkById を使用してレコードを小さなバッチ単位で処理してください。

  • パイプラインでは --force フラグを使用する Laravelが確認を求めてくると、自動デプロイパイプラインが停止してしまいます。デプロイ用スクリプトでは、次のコマンドを使用してください: php artisan migrate --force

  • テーブルロックに注意する 大規模なテーブルでカラムを変更したりインデックスを追加したりすると、そのテーブルがロックされます。これによりダウンタイムが発生します。非常に大きなテーブルの場合は、オンライン・スキーマ変更ツールを検討するか、トラフィックの少ない時間帯に変更を実行してください。

プッシュ前のチェックリスト: • down メソッドは動作するか? • ローカルでロールバックをテストしたか? • 古いものを編集するのではなく、新しいマイグレーションを作成しているか? • 新しいカラムは nullable か、あるいはデフォルト値があるか? • カラムを削除する前にバックアップは取ってあるか?

出典: https://dev.to/denisgusto1/migrations-que-nao-quebram-em-producao-o-guia-que-ninguem-te-deu-363o