Laravel 5.5使用生产数据库整合迁移

时间:2017-09-05 13:21:46

标签: php mysql laravel database-migration laravel-5.5

希望我能解释清楚。

我有一个Laravel应用程序,已经生产了一分钟。所以,我有一堆迁移文件,有很多变化。我想整合这些迁移文件而不会丢失数据库。

认为的方式可行:

  1. 将所有生产表迁移到所需状态。
  2. 将所有迁移文件合并为所需的最少文件数。
  3. 清除迁移表。
  4. 运行迁移或填充迁移表。
  5. 我希望这样做的部分原因是因为我希望公开一些服务提供商,并尽可能使用最干净的迁移设置。

    困难的版本可能是:

    1. 备份或复制表。
    2. 运行迁移。
    3. 编写并运行脚本以填充“干净”表格。
    4. 希望有一种比这更简单的方法。

      编辑(来自评论):我有一个包含大约50多个迁移文件的生产数据库 - 一些小的更改,一些大的更改。如果我合并,所需的迁移数量大约为12左右。我想整合迁移文件,但仍然能够在生产中执行migrate:rollback - 而不是我想要的。

4 个答案:

答案 0 :(得分:6)

经过几次过度设计和过于聪明的解决方案尝试之后,我认为以下是解决问题的可行方法。

tl;博士:

  • 从任何地方构建架构的迁移任意一侧的Bookend迁移。
  • 更新项目。
  • 迁移。
  • 删除书挡和之前的所有迁移。
  • 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

我们会创建另一个迁移:

  • 2017_09_05_000004_pre_refresh.php

我们将根据我们现在的知识创建另一个迁移:

  • 2017_09_05_000005_create_some_table.php

我们将创建最后一个发生数据迁移的书挡:

  • 2017_09_05_000006_post_refresh.php

前四次迁移将不会运行,因为它们已经存在。

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

不需要打倒,因为这是一次性交易。这将首先运行,这将导致重命名数组中列出的所有表。然后将运行合并(优化)迁移。

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

运行此功能后,您可以从pre_refresh和之前删除所有迁移。和post_refresh一样。然后,您可以进入migrations表并删除这些迁移的条目。

删除条目并非完全必要,但如果您migrate:rollback,您将收到错误消息,指出无法找到迁移。

注意事项

  1. 如果架构不是按设计模块化的,那么它可能非常麻烦。但是,如果您已将代码分离为服务,那么它看起来会更容易一些。
  2. Laravel错误处理和迁移过程中的消息非常有限;所以,调试可能很困难。
  3. 强烈建议您从应用/服务中最稳定的表开始。此外,从您的应用程序的基础开始也可能是有益的。
  4. 注意:当我在制作中实际执行此操作时,不仅仅是我的本地(一遍又一遍),如果没有更好的答案,那么我会接受这一点。

    考虑

    如果您通过谨慎的迁移将应用程序分解为服务提供商,那么您可以在运行迁移时在/config/app中注释掉服务提供商。这样,您可以为现在基线的服务创建批处理。因此,我们假设您进行了以下迁移,其中每个字母代表一次迁移,每个重复的字母代表相同的服务:

    • A
    • C
    • A
    • C
    • A

    合并服务A:

    • C
    • C
    • A

    合并B:

    • C
    • C
    • A

    合并C:

    • A
    • C

    <强>更新

    到目前为止,54次迁移已降至27次。我甚至从大型up()down()方法中删除了一些架构更改,并将它们分开进行迁移。这里好的副作用是批次。我从基表开始迁移,其中支持其他所有内容;因此,回滚更多的是服务。

答案 1 :(得分:4)

看来你的做法是错误的。通常,您不应该触摸迁移,因此没有必要合并它们。特别是如果您在生产服务器中推送代码,则根本不应该触摸。

总而言之 - 迁移是为了帮助您保持数据库架构,但如果您想要使用它们,合并它们或重建,没有人会阻止您,但如果您犯了错误,您可以打破容易的东西。

通过小的更改进行多次迁移没有任何问题 - 这是它的工作原理,您对PHP文件进行了更改,您在架构中进行了更改。

答案 2 :(得分:1)

您可以使用库“xethron/migrations-generator”。这是repo

安装后,基本用法: php artisan migrate:generate

有关此问题的一些讨论at laracast

答案 3 :(得分:0)

我在寻找有关合并(laravel 称之为压缩)迁移的信息时发现了这个问题。我想我会为将来寻找此信息的任何人提供答案。

Laravel 8.0 现在允许这样做:

./artisan schema:dump 同时使用您的数据库 cli 客户端将数据库架构转储导出到 Laravel 的 database/schema 文件夹中。

未来对 ./artisan migrate 的调用将首先执行架构文件,如果没有在目标数据库上运行迁移,那么它将在存储在架构转储文件中的最后一个迁移之后选取并运行所有迁移。

您可以在此处阅读更多信息Laravel 8.0 Squash Database Migrations