Help us understand the problem. What is going on with this article?

Laravel 8 の新機能!マイグレーションスカッシングで肥大化したマイグレーションファイルを1つにまとめる

大規模または長期間運用されているアプリケーションでは、
数年以上前に作成されたマイグレーションファイルが膨大な数になってきます。

データベーステストを行っているプロジェクトでは、マイグレーションを適用するのに時間がかかりテストの速度が低下する懸念があります。
これの解決策として、Laravel 8ではマイグレーションスカッシング(スキーマダンプ)と呼ばれる新機能が追加されました。

mysqldump まはた pgdump を使用して現在のスキーマの状態からダンプを作成します。
(MySQL、PostgreSQL、SQLiteデータベースのみサポート)

公式ドキュメント・ソース

マイグレーションファイルを確認

初期状態のままですが...下記のマイグレーションファイルがあるとします。

$ ls -1 database/migrations
2014_10_12_000000_create_users_table.php
2014_10_12_100000_create_password_resets_table.php
2019_08_19_000000_create_failed_jobs_table.php

スキーマダンプ コマンド

$ php artisan schema:dump

--prune オプションを付けると、既存のマイグレーションファイルの削除が行われます。

$ php artisan schema:dump --prune

database/schema/mysql-schema.sql が生成されます。
/database/schema/<DB_CONNECTION>-schema.mysql

database/schema/mysql-schema.sql
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `failed_jobs` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `uuid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `connection` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `migrations` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `migration` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `batch` int NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `password_resets` (
  `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `token` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  KEY `password_resets_email_index` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email_verified_at` timestamp NULL DEFAULT NULL,
  `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

INSERT INTO `migrations` VALUES (1,'2014_10_12_000000_create_users_table',1);
INSERT INTO `migrations` VALUES (2,'2014_10_12_100000_create_password_resets_table',1);
INSERT INTO `migrations` VALUES (3,'2019_08_19_000000_create_failed_jobs_table',1);

migrations 以外のテーブルのデータはダンプされず、テーブル構成のみダンプされるみたいです。(マイグレーションなのにデータまでダンプされたら困りますが...)

マイグレーションを実行する

$ php artisan migrate:reset
$ php artisan migrate
Loading stored database schema: /Users/ucan-lab/laravel-love/backend/database/schema/mysql-schema.sql
Loaded stored database schema. (128.57ms)
Nothing to migrate.

mysql-schema.sql が読み込まれて、既存のマイグレーションファイルは無視されてます。

スキーマダンプのメリット

前述の通り、データベーステストが高速化されるメリットがあります。

また、スキーマダンプはマイグレーションファイルではなく mysqldump コマンドを使って現在のデータベースからダンプファイルを作成されています。
本来の用途とは違うかもしれませんが、マイグレーションファイルでデータベースが管理されていないプロジェクトからLaravelに移行する際はとても役に立つ機能ではないでしょうか。

使ってみた感想

mysqldump コマンドをLaravelで実行しているので、Dockerでやろうとするとmysqldumpコマンドをコンテナ内で使えるようにしてあげる必要があるし、debianのdefault-mysql-clientはMariaDBに統合されたようでLaravelで実行しているオプションが存在していなかったりとDockerで頑張ろうとすると手間かもしれません...今回はローカルで試してみました。

参考

ucan-lab
Backend Developer at ROLO. I love PHP and I'm focusing on Laravel, Docker, GraphQL.
https://u-can.pro
miraito-inc
システムデザインを中心に置いた開発により高品質で使いやすいシステムを提供いたします。業務システム構築、アプリ開発、コンサルティングまで幅広く手がけています。
https://miraito-inc.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした