Laravel 5.5 使用生产数据库整合迁移
Laravel 5.5 Consolidate migrations w/ production database
希望我能解释清楚。
我有一个 Laravel 应用程序已投入生产一分钟。所以,我有一堆有很多变化的迁移文件。我想在不丢失数据库的情况下整合这些迁移文件。
我认为这样可行的方式:
- 将所有生产 table 迁移到所需状态。
- 将所有迁移文件合并为所需的最少数量的文件。
- 清除迁移 table。
- 运行 迁移或填充迁移 table。
我想这样做的部分原因是因为我想让一些服务提供商 public 拥有尽可能干净的迁移集。
困难的版本可能是:
- 备份或复制 tables.
- 运行 迁移。
- 编写 运行 脚本来填充 "clean" tables.
只是希望有比这更简单的方法。
编辑(来自评论):我有一个生产数据库,其中包含大约 50 多个迁移文件 - 一些小改动,一些大改动。如果我合并,所需的迁移数量大约为 12 次左右。我想合并迁移文件,但仍然能够在生产环境中执行 migrate:rollback
- 但我不会。
看来你做错了。通常你不应该触及你的迁移,所以没有必要合并它们。特别是如果您将代码推送到生产服务器中,则根本不应该触摸。
总而言之 - 迁移是为了帮助您保持数据库架构应有的样子,但如果您想使用它们、合并它们或重建它们,没有人会阻止您,但如果您犯了错误,您可以轻易打破东西。
进行多次迁移并进行少量更改并没有错 - 这就是它的工作原理,您对 PHP 文件进行更改,对架构进行更改。
经过几次过度设计和过于聪明的解决方案尝试,我认为以下是解决问题的可行方案。
tl;博士:
- 从无到有构建架构的迁移两侧的书挡迁移。
- 更新项目。
- 迁移。
- 删除书挡和所有以前的迁移。
- 从
migrations
table 中删除记录。
第一个书挡重命名了受影响的 table。第二个书立将数据从重命名的 tables 复制到新的 tables,然后删除重命名的 tables。
注意:您可以在书挡内随心所欲,这只是最低限度。
那么,让我们假设您使用以下类似的迁移方式:
- 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);
}
}
}
不需要降价,因为这是一次性交易。这将首先 运行,这将导致数组中列出的所有 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
table 并删除这些迁移的条目。
删除条目并非完全必要,但如果您migrate:rollback
您将收到错误消息,指出无法找到迁移。
注意事项
- 如果架构在设计上不是模块化的,它可能会非常麻烦。但是,如果您将代码分离到服务中,它似乎会更容易一些。
- Laravel 迁移期间的错误处理和消息非常有限;因此,调试可能很困难。
- 强烈建议从 app/service 中最多的 table table 开始。此外,从那些对您的应用程序来说是基础的开始也可能被证明是有益的。
注意:当我实际在生产中这样做时,不仅仅是我的本地(一遍又一遍),如果没有更好的答案,那么我会接受这个。
注意事项
如果您通过谨慎的迁移将您的应用程序分解为服务提供商,那么您可以在 运行 迁移时在 /config/app
中注释掉服务提供商。这样您就可以为现在的基线服务创建一个批处理。因此,假设您有以下迁移,其中每个字母代表一个迁移,每个重复的字母代表相同的服务:
- 一个
- B
- C
- 一个
- C
- B
- 一个
整合服务A后:
- B
- C
- C
- B
- 一个
合并B后:
- C
- C
- 一个
- B
巩固C后:
- 一个
- B
- C
更新
到目前为止,54 次迁移减少到 27 次。我什至从大型 up()
和 down()
方法中提取了一些架构更改,并将它们分开迁移。这里好的副作用是批处理。我从基础 tables 开始迁移,其他一切都基于该基础得到支持;因此,回滚是一个服务一个服务。
您可以使用库“xethron/migrations-generator
”。这是 repo.
安装后,基本使用:
php artisan migrate:generate
找到一些关于此的讨论at laracast。
我在查找有关合并(laravel 称之为压缩)迁移的信息时发现了这个问题。我想我会为将来寻找此信息的任何人提供答案。
Laravel 8.0 现在允许:
./artisan schema:dump
同时使用您的数据库 cli 客户端将数据库模式转储导出到 laravel 的 database/schema 文件夹中。
如果目标数据库上 运行 没有迁移,以后对 ./artisan migrate
的调用将首先执行架构文件,然后它会选择并 运行 最后一次之后的所有迁移一个存储在架构转储文件中。
您可以在此处阅读更多内容Laravel 8.0 Squash Database Migrations
希望我能解释清楚。
我有一个 Laravel 应用程序已投入生产一分钟。所以,我有一堆有很多变化的迁移文件。我想在不丢失数据库的情况下整合这些迁移文件。
我认为这样可行的方式:
- 将所有生产 table 迁移到所需状态。
- 将所有迁移文件合并为所需的最少数量的文件。
- 清除迁移 table。
- 运行 迁移或填充迁移 table。
我想这样做的部分原因是因为我想让一些服务提供商 public 拥有尽可能干净的迁移集。
困难的版本可能是:
- 备份或复制 tables.
- 运行 迁移。
- 编写 运行 脚本来填充 "clean" tables.
只是希望有比这更简单的方法。
编辑(来自评论):我有一个生产数据库,其中包含大约 50 多个迁移文件 - 一些小改动,一些大改动。如果我合并,所需的迁移数量大约为 12 次左右。我想合并迁移文件,但仍然能够在生产环境中执行 migrate:rollback
- 但我不会。
看来你做错了。通常你不应该触及你的迁移,所以没有必要合并它们。特别是如果您将代码推送到生产服务器中,则根本不应该触摸。
总而言之 - 迁移是为了帮助您保持数据库架构应有的样子,但如果您想使用它们、合并它们或重建它们,没有人会阻止您,但如果您犯了错误,您可以轻易打破东西。
进行多次迁移并进行少量更改并没有错 - 这就是它的工作原理,您对 PHP 文件进行更改,对架构进行更改。
经过几次过度设计和过于聪明的解决方案尝试,我认为以下是解决问题的可行方案。
tl;博士:
- 从无到有构建架构的迁移两侧的书挡迁移。
- 更新项目。
- 迁移。
- 删除书挡和所有以前的迁移。
- 从
migrations
table 中删除记录。
第一个书挡重命名了受影响的 table。第二个书立将数据从重命名的 tables 复制到新的 tables,然后删除重命名的 tables。
注意:您可以在书挡内随心所欲,这只是最低限度。
那么,让我们假设您使用以下类似的迁移方式:
- 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);
}
}
}
不需要降价,因为这是一次性交易。这将首先 运行,这将导致数组中列出的所有 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
table 并删除这些迁移的条目。
删除条目并非完全必要,但如果您migrate:rollback
您将收到错误消息,指出无法找到迁移。
注意事项
- 如果架构在设计上不是模块化的,它可能会非常麻烦。但是,如果您将代码分离到服务中,它似乎会更容易一些。
- Laravel 迁移期间的错误处理和消息非常有限;因此,调试可能很困难。
- 强烈建议从 app/service 中最多的 table table 开始。此外,从那些对您的应用程序来说是基础的开始也可能被证明是有益的。
注意:当我实际在生产中这样做时,不仅仅是我的本地(一遍又一遍),如果没有更好的答案,那么我会接受这个。
注意事项
如果您通过谨慎的迁移将您的应用程序分解为服务提供商,那么您可以在 运行 迁移时在 /config/app
中注释掉服务提供商。这样您就可以为现在的基线服务创建一个批处理。因此,假设您有以下迁移,其中每个字母代表一个迁移,每个重复的字母代表相同的服务:
- 一个
- B
- C
- 一个
- C
- B
- 一个
整合服务A后:
- B
- C
- C
- B
- 一个
合并B后:
- C
- C
- 一个
- B
巩固C后:
- 一个
- B
- C
更新
到目前为止,54 次迁移减少到 27 次。我什至从大型 up()
和 down()
方法中提取了一些架构更改,并将它们分开迁移。这里好的副作用是批处理。我从基础 tables 开始迁移,其他一切都基于该基础得到支持;因此,回滚是一个服务一个服务。
您可以使用库“xethron/migrations-generator
”。这是 repo.
安装后,基本使用:
php artisan migrate:generate
找到一些关于此的讨论at laracast。
我在查找有关合并(laravel 称之为压缩)迁移的信息时发现了这个问题。我想我会为将来寻找此信息的任何人提供答案。
Laravel 8.0 现在允许:
./artisan schema:dump
同时使用您的数据库 cli 客户端将数据库模式转储导出到 laravel 的 database/schema 文件夹中。
如果目标数据库上 运行 没有迁移,以后对 ./artisan migrate
的调用将首先执行架构文件,然后它会选择并 运行 最后一次之后的所有迁移一个存储在架构转储文件中。
您可以在此处阅读更多内容Laravel 8.0 Squash Database Migrations