将 "resetting" 损坏的迁移修复到当前模式
Fix broken migrations by "resetting" to current schema
我们已经接管了一个旧的(3 年)Symfony 3.3 项目,它使用 doctrine-migrations 1.0 包来处理迁移。不幸的是,迁移脚本已经损坏了一段时间而没有任何人注意到,因此您无法在不检查现有数据库的情况下从源代码进行全新构建。
我想解决这个问题,这样 运行ning composer doctrine:migrate
基本上只是 运行 一个创建当前模式的虚拟脚本。我该怎么做才能使现有模式 运行 不会中断?
我想我会按照这些思路做一些事情:
- 检查一个干净的项目(有错误的旧迁移)
- 获取生产数据库转储
- 将生产数据库模式转储到 SQL 文件
- 删除旧的迁移
- 创建一个版本号与错误迁移中"current"/最高编号相同的迁移文件
- 运行迁移
作为最后一步,通过删除数据库、导入生产数据库转储并然后 运行ning migrate
验证这是否真的有效,以验证没有任何中断。我只是不确定如何在 Doctrine 包的上下文中执行此操作(我是 PHP 的新手),即使在查阅了文档(似乎没有涵盖这种情况)之后也是如此。
我完全按照上面的草图做了,而且效果很好。对于上下文,我有这组迁移脚本的元数据:
"SELECT * FROM migration_versions"
┌────────────────┐
│ version │
├────────────────┤
│ 20161112122228 │
│ 20161113143631 │
│ 20161122223420 │
│ 20161124162611 │
│ 20161128151448 │
│ 20161207194257 │
│ 20161208114104 │
│ 20161208114105 │
│ 20170123074229 │
│ 20170125081729 │
│ 20170130080734 │
│ 20170130080820 │
│ 20170131082751 │
│ 20170201074705 │
│ 20170208092040 │
│ 20170208092917 │
│ 20170208103930 │
│ 20170608042313 │
│ 20170628044258 │
│ 20170930061118 │
└────────────────┘
这意味着我也会在 app/DoctrineMigrations/
中有一组相应的文件,称为 app/DoctrineMigrations/Version20170930061118.php
之类的东西。只有最后一个文件会以实际内容结束,其余的将是空的假人。
Git 我的更改日志
创建一个虚拟模板来替换现有迁移的内容
在某些时候,现有迁移已停止工作。这是在 2020 年 3 月 1 日左右发现的。
这意味着无法使用 doctrine:migrations:migrate 命令从新源开始开发,因为它很早就失败了。
与此同时,现有数据库包含有关过去执行过哪些迁移的元数据,因此任何修复都需要向迁移包发出信号表明这些 are/have 已执行。
建议的修复方法是创建简单的 "marker classes" 来满足迁移已经 done/exist 的信号需求,然后将最后迁移的内容 class 替换为简单地创建一个与生产数据库的当前状态匹配的模式的脚本。
这是第一步。
将所有迁移脚本内容替换为空内容
这是修复中的第 2 步。基本上为 app/DoctrineMigrations/*.php 中的每个文件做一个循环,并将其替换为虚拟模板。这是完整的脚本
$ git show 773ccebee20425d7025152b338282f0a0034556f:app/DoctrineMigrations/create-dummy-migrations.sh
#!/bin/bash
for file in Version*.php; do
CLASS=$(basename $file .php)
sed -e "s/CLASSNAME/$CLASS/" template.php > $file
done
这是完整的模板
git show 773ccebee20425d7025152b338282f0a0034556f:app/DoctrineMigrations/template.php
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Dummy migration to fix faulty migration scripts issue
* discovered in March 2020.
*/
class CLASSNAME extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->addSql('COMMENT ON table migration_versions IS \'migrations from 2016-2017 are stubs\'');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
}
}
删除助手
从产品转储架构
使用脚本清理了架构
grep -v -- '--' production-schema-2020.sql \
| awk 1 ORS=' ' \
| sed -r -e 's/;\s+/; /g' > cleaned.sql
从 SQL 脚本生成 Doctrine PHP 语句
脚本:sed -e "s/^(.*);/$this->addSql('');/" cleaned.sql > cleaned-sql-to-php-statements.txt
将架构语句移至上次迁移
基本上是将 cleaned-sql-to-php-statements.txt
中的内容复制粘贴到
删除临时文件
对生成的 PHP SQL 语句进行细微调整和清理
我们已经接管了一个旧的(3 年)Symfony 3.3 项目,它使用 doctrine-migrations 1.0 包来处理迁移。不幸的是,迁移脚本已经损坏了一段时间而没有任何人注意到,因此您无法在不检查现有数据库的情况下从源代码进行全新构建。
我想解决这个问题,这样 运行ning composer doctrine:migrate
基本上只是 运行 一个创建当前模式的虚拟脚本。我该怎么做才能使现有模式 运行 不会中断?
我想我会按照这些思路做一些事情:
- 检查一个干净的项目(有错误的旧迁移)
- 获取生产数据库转储
- 将生产数据库模式转储到 SQL 文件
- 删除旧的迁移
- 创建一个版本号与错误迁移中"current"/最高编号相同的迁移文件
- 运行迁移
作为最后一步,通过删除数据库、导入生产数据库转储并然后 运行ning migrate
验证这是否真的有效,以验证没有任何中断。我只是不确定如何在 Doctrine 包的上下文中执行此操作(我是 PHP 的新手),即使在查阅了文档(似乎没有涵盖这种情况)之后也是如此。
我完全按照上面的草图做了,而且效果很好。对于上下文,我有这组迁移脚本的元数据:
"SELECT * FROM migration_versions"
┌────────────────┐
│ version │
├────────────────┤
│ 20161112122228 │
│ 20161113143631 │
│ 20161122223420 │
│ 20161124162611 │
│ 20161128151448 │
│ 20161207194257 │
│ 20161208114104 │
│ 20161208114105 │
│ 20170123074229 │
│ 20170125081729 │
│ 20170130080734 │
│ 20170130080820 │
│ 20170131082751 │
│ 20170201074705 │
│ 20170208092040 │
│ 20170208092917 │
│ 20170208103930 │
│ 20170608042313 │
│ 20170628044258 │
│ 20170930061118 │
└────────────────┘
这意味着我也会在 app/DoctrineMigrations/
中有一组相应的文件,称为 app/DoctrineMigrations/Version20170930061118.php
之类的东西。只有最后一个文件会以实际内容结束,其余的将是空的假人。
Git 我的更改日志
创建一个虚拟模板来替换现有迁移的内容
在某些时候,现有迁移已停止工作。这是在 2020 年 3 月 1 日左右发现的。
这意味着无法使用 doctrine:migrations:migrate 命令从新源开始开发,因为它很早就失败了。
与此同时,现有数据库包含有关过去执行过哪些迁移的元数据,因此任何修复都需要向迁移包发出信号表明这些 are/have 已执行。
建议的修复方法是创建简单的 "marker classes" 来满足迁移已经 done/exist 的信号需求,然后将最后迁移的内容 class 替换为简单地创建一个与生产数据库的当前状态匹配的模式的脚本。
这是第一步。
将所有迁移脚本内容替换为空内容
这是修复中的第 2 步。基本上为 app/DoctrineMigrations/*.php 中的每个文件做一个循环,并将其替换为虚拟模板。这是完整的脚本
$ git show 773ccebee20425d7025152b338282f0a0034556f:app/DoctrineMigrations/create-dummy-migrations.sh
#!/bin/bash
for file in Version*.php; do
CLASS=$(basename $file .php)
sed -e "s/CLASSNAME/$CLASS/" template.php > $file
done
这是完整的模板
git show 773ccebee20425d7025152b338282f0a0034556f:app/DoctrineMigrations/template.php
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Dummy migration to fix faulty migration scripts issue
* discovered in March 2020.
*/
class CLASSNAME extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->addSql('COMMENT ON table migration_versions IS \'migrations from 2016-2017 are stubs\'');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
}
}
删除助手
从产品转储架构
使用脚本清理了架构
grep -v -- '--' production-schema-2020.sql \
| awk 1 ORS=' ' \
| sed -r -e 's/;\s+/; /g' > cleaned.sql
从 SQL 脚本生成 Doctrine PHP 语句
脚本:sed -e "s/^(.*);/$this->addSql('');/" cleaned.sql > cleaned-sql-to-php-statements.txt
将架构语句移至上次迁移
基本上是将 cleaned-sql-to-php-statements.txt
中的内容复制粘贴到
删除临时文件
对生成的 PHP SQL 语句进行细微调整和清理