sql >> Database >  >> RDS >> Mysql

Laravel 5.5 Consolideer migraties met productiedatabase

Na een paar overontwikkelde en overdreven slimme oplossingspogingen, denk ik dat het volgende een werkbare oplossing voor het probleem is.

tl;dr:

  • Bookend-migraties aan weerszijden van migratie(s) die het schema vanuit het niets opbouwen.
  • Project bijwerken.
  • Migreren.
  • Verwijder boekensteunen en alle eerdere migraties.
  • Verwijder records van migrations tafel.

De eerste boekensteun hernoemt de betreffende tafels. De tweede boekensteun kopieert de gegevens van de hernoemde tabellen naar de nieuwe tabellen en verwijdert vervolgens de hernoemde tabellen.

Opmerking:je kunt binnen de boekensteunen doen wat je wilt, dit is slechts een minimum.

Dus, laten we zeggen dat je iets als het volgende voor migraties:

  • 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

We zouden een andere migratie maken:

  • 2017_09_05_000004_pre_refresh.php

We zouden een nieuwe migratie maken op basis van de kennis die we nu hebben:

  • 2017_09_05_000005_create_some_table.php

We zouden de laatste boekensteun maken, waar gegevensmigratie zal plaatsvinden:

  • 2017_09_05_000006_post_refresh.php

De eerste vier migraties worden niet uitgevoerd omdat ze al zijn uitgevoerd.

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

Geen behoefte aan een down, want dit is een eenmalige deal. Dit wordt eerst uitgevoerd, wat ertoe zou moeten leiden dat alle tabellen in de array worden hernoemd. Daarna worden de geconsolideerde (geoptimaliseerde) migratie(s) uitgevoerd.

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

Nadat u dit hebt uitgevoerd, kunt u al uw migraties verwijderen uit de pre_refresh en eerder. Evenals de post_refresh . Dan kun je naar de migrations gaan tabel en verwijder de items voor die migraties.

Het verwijderen van de items is niet helemaal nodig, maar als u migrate:rollback u krijgt foutmeldingen waarin staat dat de migratie niet kan worden gevonden.

Voorbehoud

  1. Als de architectuur niet modulair van opzet is, kan het behoorlijk omslachtig zijn. Als je je code echter hebt opgesplitst in services, lijkt het een beetje eenvoudiger te zijn.
  2. Laravel-foutafhandeling en berichten tijdens migraties zijn zeer beperkt; dus debuggen kan moeilijk zijn.
  3. Beveel ten zeerste aan te beginnen met de meest stabiele tabellen in uw app/service. Verder kan het nuttig zijn om te beginnen met degene die essentieel zijn voor uw app.

Opmerking:als ik dit in productie doe, niet alleen mijn lokale (steeds opnieuw), en als er geen beter antwoord is, dan accepteer ik dit.

Overwegingen

Als u uw applicatie opsplitst in serviceproviders met discrete migraties, dan kunt u de serviceprovider uitspreken in /config/app wanneer u de migraties uitvoert. Op deze manier maakt u een batch voor de nu gebaselinede service. Stel dat u de volgende migraties heeft waarbij elke letter een migratie vertegenwoordigt en elke dubbele letter dezelfde service:

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

Na het consolideren van service A:

  • B
  • C
  • C
  • B
  • A

Na het consolideren van B:

  • C
  • C
  • A
  • B

Na consolidering van C:

  • A
  • B
  • C

bijwerken

54 migraties tot nu toe 27. Ik heb zelfs enkele schemawijzigingen uit de grote up() . gehaald en down() methoden en maak ze afzonderlijke migraties. Het leuke neveneffect hier zijn de batches. Ik migreerde te beginnen met de basistabellen waarop al het andere wordt ondersteund; daarom is terugdraaien meer service per service.



  1. Foutcode:1052. Kolom 'ATTRIBUTE' in veldlijst is dubbelzinnig

  2. Een array doorgeven aan een opgeslagen procedure van SQL Server

  3. JPA-query in meerdere tabellen met veel-op-veel-relatie

  4. hoe selecteer ik alle kolommen zonder PRIMARY-sleutel in mysql?