Mysql
 sql >> Base de données >  >> RDS >> Mysql

Laravel 5.5 Consolider les migrations avec la base de données de production

Après quelques tentatives de solution trop élaborées et trop intelligentes, je pense que ce qui suit est une solution viable au problème.

tl;dr :

  • Migrations serre-livres de part et d'autre des migrations qui créent le schéma à partir de rien.
  • Projet de mise à jour.
  • Migrez.
  • Supprimez les serre-livres et toutes les migrations précédentes.
  • Supprimer les enregistrements des migrations table.

Le premier serre-livres renomme les tables affectées. Le deuxième serre-livres copie les données des tables renommées vers les nouvelles tables, puis supprime les tables renommées.

Remarque :Vous pouvez faire ce que vous voulez à l'intérieur des serre-livres, c'est juste un minimum.

Alors, disons quelque chose comme ce qui suit pour les migrations :

  • 2017_09_05_000000_create_some_table.php
  • 2017_09_05_000001_add_field_x_to_some_table.php
  • 2017_09_05_000002_add_field_y_to_some_table.php
  • 2017_09_05_000003_add_field_z_to_some_table.php

Nous créerions une autre migration :

  • 2017_09_05_000004_pre_refresh.php

Nous créerions une autre migration basée sur les connaissances que nous avons maintenant :

  • 2017_09_05_000005_create_some_table.php

Nous créerions le dernier serre-livre, où la migration des données aura lieu :

  • 2017_09_05_000006_post_refresh.php

Les quatre premières migrations ne seront pas exécutées car elles l'ont déjà été.

/** 2017_09_05_000004_pre_refresh.php */
class PreRefresh extends Migration
{
    public function up()
    {
        $prefix = 'zz_';
        $tablesToRename = [
            'foos',
            'bars'
        ];

        foreach($tablesToRename as $table) {
            Schema::rename($table, $prefix . $table);
        }
    }
}

Pas besoin d'un down, car c'est un one shot deal. Cela s'exécutera en premier, ce qui devrait entraîner le changement de nom de toutes les tables répertoriées dans le tableau. Ensuite, la ou les migrations consolidées (optimisées) seront exécutées.

/** 2017_09_05_000006_post_refresh.php */
class PostRefresh extends Migration
{
    public function up()
    {
        // Do what you need to do.
        // If you cannot use your models, just use DB::table() commands.

        $foos = DB::table('zz_foos')->get();
        foreach ($foos as $foo) {
            DB::table('foo')->insert([
                    'id'         => $foo->id,
                    'created_at' => $foo->created_at,
                    'updated_at' => $foo->updated_at
                ]);
        }

        $bars = DB::table('zz_bars')->get();
        foreach ($bars as $bar) {
            DB::table('bar')->insert([
                    'id'         => $bar->id,
                    'created_at' => $bar->created_at,
                    'updated_at' => $bar->updated_at,
                    'foo_id'     => $bar->foo_id
                ]);
        }

        // Tear down.
        $prefix = 'zz_';
        $tablesToRename = [
            'foo',
            'bar'
        ];

        foreach ($tablesToRename as $table) {
            DB::statement('SET FOREIGN_KEY_CHECKS=0');
            Schema::dropIfExists($prefix . $table);
            DB::statement('SET FOREIGN_KEY_CHECKS=1');
        }
    }
}

Après l'avoir exécuté, vous pouvez supprimer toutes vos migrations du pre_refresh et avant. Ainsi que le post_refresh . Ensuite, vous pouvez vous diriger vers les migrations table et supprimez les entrées pour ces migrations.

La suppression des entrées n'est pas entièrement nécessaire, mais si vous migrate:rollback vous recevrez des messages d'erreur indiquant que la migration est introuvable.

Mises en garde

  1. Si l'architecture n'est pas modulaire par conception, elle peut être assez lourde. Cependant, si vous avez séparé votre code en services, cela semble être un peu plus facile.
  2. La gestion des erreurs Laravel et les messages lors des migrations sont très limités ; ainsi, le débogage pourrait être difficile.
  3. Nous vous recommandons vivement de commencer par les tables les plus stables de votre application/service. De plus, commencer par ceux qui sont fondamentaux pour votre application peut également s'avérer bénéfique.

Remarque :Lorsque je fais cela en production, pas seulement dans ma section locale (encore et encore), et s'il n'y a pas de meilleure réponse, alors je l'accepterai.

Considérations

Si vous divisez votre application en fournisseurs de services avec des migrations discrètes, vous pouvez commenter le fournisseur de services dans /config/app lorsque vous exécutez les migrations. De cette façon, vous créez un lot pour le service désormais référencé. Supposons donc que vous ayez les migrations suivantes, où chaque lettre représente une migration et chaque lettre en double représente le même service :

  • A
  • B
  • C
  • A
  • C
  • B
  • A

Après consolidation du service A :

  • B
  • C
  • C
  • B
  • A

Après consolidation B :

  • C
  • C
  • A
  • B

Après avoir consolidé C :

  • A
  • B
  • C

mettre à jour

54 migrations contre 27 jusqu'à présent. J'ai même retiré quelques modifications de schéma de grands up() et down() méthodes et en faire des migrations séparées. Le bel effet secondaire ici est les lots. J'ai migré en commençant par les tables de base sur lesquelles tout le reste est pris en charge ; par conséquent, la restauration est plus service par service.