Make組ブログ

Python、Webサービスや製品開発、ライブラリー開発についてhirokikyが書きます

Djangoのマイグレーションで実行される処理(とSQL)を確認する方法

Djangoマイグレーションで実行される処理(とSQL)を確認する方法を説明します。

先日の記事では「Djangoマイグレーションを無停止で反映する方法」を説明しましたが、そのためにはマイグレーションでどんなSQLが実行されるかが重要になります。

blog.hirokiky.org

もちろんマイグレーションファイルを開いて見れば分かりますが、Djangoのコマンドから便利に確認したり、実際に発行されるSQLを確認しておくほうが安全です。

実行されるマイグレーションのプランを確認する

Djangomigrate --plan コマンドを使って、実行されるマイグレーションのプランを確認できます。 この例では blog アプリの 00010002 というマイグレーションが適応されていない状態です。

python manage.py migrate --plan
Planned operations:
blog.0001_initial
    Create model Post
blog.0002_post_published_at
    Add field published_at to post

--plan を見るとそれぞれのマイグレーションでどのような処理が実行されるかが分かります。 この例では以下の意味になります。

  • 0001: モデルPostを作成する
  • 0002: postにpublished_atフィールドを追加する

両方のマイグレーションファイルともテーブルやカラムを追加するものなので、(基本的に)Webアプリのリリース前にマイグレーションを実行できます。

マイグレーションで実行されるSQLを確認する

migrate --plan で内容を確認できるとはいえ、実際にマイグレーションで実行されるSQLを確認しておくほうが安心です。 Djangoにおいてマイグレーションで実行されるSQLを確認するには、 sqlmigrate コマンドを使います。 アプリケーション名 <app_name>マイグレーションの名前 <migration_name> を指定して使います。

python manage.py sqlmigrate <app_name> <migration_name>

例えば blog アプリの 0002_post_published_at.py マイグレーションファイルで実行されるSQLを確認するには、以下のようにします。

python manage.py sqlmigrate blog 0002

こうすることで 0002_post_published_at.py が反映されるときに実行されるSQLが表示されます。

BEGIN;
--
-- Add field published_at to post
--
ALTER TABLE `blog_post` ADD COLUMN `published_at` datetime(6) NULL;
COMMIT;

SQLの内容を見ることで、マイグレーション実行時にどのような処理がデータベースに行われるかが分かります。 Webアプリを無停止のままマイグレーションを反映するときは、このSQLの内容に応じてどのようにリリースすべきかが変わります。

本番環境と同じデータベースバックエンドを使って確認しよう

ただし、 sqlmigrate の結果は settings で使われているデータベース(DATABASES 設定の内容)に応じて結果は変わります。 必ず運用している環境と同じデータベースバックエンドを使ってSQLを確認しましょう。 例えば、上記の例はMySQLバックエンドで出力しましたが、SQLite3バックエンドでは以下のような別のSQLになります。

BEGIN;
--
-- Add field published_at to post
--
CREATE TABLE "new__blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "published_at" datetime NULL, "body" text NOT NULL);
INSERT INTO "new__blog_post" ("id", "body", "published_at") SELECT "id", "body", NULL FROM "blog_post";
DROP TABLE "blog_post";
ALTER TABLE "new__blog_post" RENAME TO "blog_post";
COMMIT;

まとめ

以下2つのコマンドを使ってマイグレーションの内容を確認しましょう。

これでマイグレーションSQLの内容が分かったらWebアプリを無停止でマイグレーションをできるかを検討しましょう。

blog.hirokiky.org