🎈
【Rails】rails db:migrate と rails db:schema:load の挙動の違い
はじめに
rails db:migrate
とrails db:schema:load
の違いについて記載します。
結論
-
何を元にマイグレーションを実行するかの違いです。
- rails db:migrate
-
マイグレーションファイル
を参照してクエリを発行。schema.rb
は参照されない。マイグレーション完了後、現在のデータベーススキーマのスナップショットがschema.rb
に反映される。
-
- rails db:schema:load
-
schema.rb
をもとにクエリを発行。マイグレーションファイル
は参照されない。
-
- rails db:migrate
-
rails db:schema:load
は既存のデータベースをリセットするので、既存のデータが全て削除される。
rails db:migrate
rails db:migrate
を実行した際の流れは下記のとおりです。
① マイグレーションファイルの実行
Railsはdb/migrateディレクトリ内にあるマイグレーションファイルをタイムスタンプの順に実行する。
このプロセスでは、まだ実行されていない(schema_migrationsテーブルにそのバージョン番号が記録されていない)マイグレーションファイルのみが対象となる。
↓
② schema_migrationsテーブルの更新
マイグレーションが成功すると、そのマイグレーションのバージョン番号(マイグレーションファイル名の接頭部分にあるタイムスタンプ)がschema_migrationsテーブルに追加される。
これにより、どのマイグレーションが既に適用されたかをRailsが追跡できるようになる。
↓
③ schema.rbの更新
マイグレーションの適用が完了すると、現在のデータベーススキーマのスナップショットがschema.rbに反映される。
このファイルはマイグレーションを実行する際に直接参照されることはない。
rails db:migrate
を実行した際のRailsのログを見てみます(①→②)
実行後のschema_migrationsテーブル
を見てみます。(②)
MySQL
SELECT * FROM schema_migrations;
+----------------+
| version |
+----------------+
| ... |
| 20240319010635 |
+----------------+
rails db:schema:load
rails db:schema:load
を実行した際の流れは下記のとおりです。
① データベースのリセット
db:schema:load は既存のデータベーススキーマ(存在する場合)を完全に無視し、schema.rb に定義されているスキーマ定義に基づいてデータベースを一から構築する。
このコマンドを実行すると、すでに存在するテーブルは削除され、新たに schema.rb に記述されている内容でテーブルが作成される。
↓
② schema.rb の利用
schema.rb ファイルが読み込まれ、その中に記述されているすべてのテーブル定義とスキーマ情報がデータベースに適用される。
schema.rb は、最後に成功したマイグレーションの状態を表しているため、db:schema:load でデータベースを構築すると、
マイグレーションを一つ一つ適用することなく、直接最新のスキーマ状態になる。
↓
③ schema_migrations テーブルの更新
schema.rb をもとにデータベーススキーマが再構築されると同時に、schema_migrations テーブルも更新される。
schema_migrations テーブルには、schema.rb に基づく最後のマイグレーションのバージョン番号が保存される。
これにより、将来的に rails db:migrate を実行した際に、どのマイグレーションから開始すればよいかがRailsによって識別される。
※ マイグレーションファイルの無視
db:schema:load コマンドは、マイグレーションファイルを一切参照しない。
マイグレーションファイルを実行するのではなく、schema.rb が持つスキーマ情報を直接データベースに適用する。
どう使い分けるのか
-
rails db:schema:load
は既存のデータを全て削除してしまうので、もちろん本番環境では使わない。 - 下記の記事にこんなことが書いてあった。なるほど..!
ローカルでは rake db:migrete , CIツール上では rake db:schema:load と使い分けるのが一般的で、そうすることによってmigrateし忘れてpushしてもCIツール上のschema.rbのバージョンが同じになるようにしてるみたい。
-
rails db:schema:load
はschema.rb
から直接マイグレーションを行うので、ローカルで新しい開発環境のセットアップをしたいときは良さそう。
Discussion