Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Laravel 5.5 Konsolidierungsmigrationen mit Produktionsdatenbank

Nach ein paar überdimensionierten und übermäßig cleveren Lösungsversuchen denke ich, dass das Folgende eine praktikable Lösung für das Problem ist.

tl;dr:

  • Bookend-Migrationen auf beiden Seiten von Migration(en), die das Schema aus dem Nichts erstellen.
  • Projekt aktualisieren.
  • Migrieren.
  • Buchstützen und alle vorherigen Migrationen löschen.
  • Löschen Sie Datensätze aus migrations Tisch.

Die erste Buchstütze benennt die betroffenen Tabellen um. Die zweite Buchstütze kopiert die Daten aus den umbenannten Tabellen in die neuen Tabellen und löscht dann die umbenannten Tabellen.

Hinweis:Sie können in den Buchstützen alles tun, was Sie möchten, dies ist nur ein Minimum.

Sagen wir mal so etwas wie das Folgende für Migrationen:

  • 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

Wir würden eine weitere Migration erstellen:

  • 2017_09_05_000004_pre_refresh.php

Wir würden basierend auf dem Wissen, das wir jetzt haben, eine weitere Migration erstellen:

  • 2017_09_05_000005_create_some_table.php

Wir würden die letzte Buchstütze erstellen, wo die Datenmigration stattfindet:

  • 2017_09_05_000006_post_refresh.php

Die ersten vier Migrationen werden nicht ausgeführt, da sie bereits ausgeführt wurden.

/** 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);
        }
    }
}

Keine Notwendigkeit für ein Down, denn dies ist ein One-Shot-Deal. Dies wird zuerst ausgeführt, was dazu führen sollte, dass alle im Array aufgelisteten Tabellen umbenannt werden. Dann werden die konsolidierten (optimierten) Migrationen ausgeführt.

/** 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');
        }
    }
}

Nachdem Sie dies ausgeführt haben, können Sie alle Ihre Migrationen aus pre_refresh löschen und vor. Sowie der post_refresh . Dann können Sie zu den migrations gehen Tabelle und löschen Sie die Einträge für diese Migrationen.

Das Löschen der Einträge ist nicht unbedingt erforderlich, aber wenn Sie migrate:rollback Sie erhalten Fehlermeldungen, die besagen, dass die Migration nicht gefunden werden kann.

Warnhinweise

  1. Wenn die Architektur nicht modular aufgebaut ist, kann sie ziemlich umständlich sein. Wenn Sie Ihren Code jedoch in Dienste unterteilt haben, scheint es etwas einfacher zu sein.
  2. Laravel-Fehlerbehandlung und Meldungen während Migrationen sind sehr begrenzt; Daher könnte das Debuggen schwierig sein.
  3. Wir empfehlen dringend, mit den stabilsten Tabellen in Ihrer App/Ihrem Dienst zu beginnen. Außerdem könnte es sich als vorteilhaft erweisen, mit den grundlegenden Elementen Ihrer App zu beginnen.

Hinweis:Wenn ich dies tatsächlich in der Produktion mache, nicht nur in meinem Lokal (immer wieder), und wenn es keine bessere Antwort gibt, dann werde ich das akzeptieren.

Überlegungen

Wenn Sie Ihre Anwendung mit diskreten Migrationen in Dienstanbieter aufteilen, können Sie den Dienstanbieter in /config/app auskommentieren wenn Sie die Migrationen ausführen. Auf diese Weise erstellen Sie einen Stapel für den jetzt als Baseline festgelegten Dienst. Angenommen, Sie haben die folgenden Migrationen, bei denen jeder Buchstabe eine Migration und jeder doppelte Buchstabe denselben Dienst darstellt:

  • A
  • B
  • K
  • A
  • K
  • B
  • A

Nach der Konsolidierung von Dienst A:

  • B
  • K
  • K
  • B
  • A

Nach Konsolidierung von B:

  • K
  • K
  • A
  • B

Nach der Konsolidierung von C:

  • A
  • B
  • K

aktualisieren

54 Migrationen bis jetzt auf 27. Ich habe sogar einige Schemaänderungen aus dem großen up() herausgezogen und down() Methoden und trennen Sie Migrationen. Der nette Nebeneffekt dabei sind die Chargen. Ich habe angefangen mit den Basistabellen migriert, auf denen alles andere unterstützt wird; Daher ist ein Rollback mehr Dienst für Dienst.