通过“重置”到当前架构来修复损坏的迁移

Posted

技术标签:

【中文标题】通过“重置”到当前架构来修复损坏的迁移【英文标题】:Fix broken migrations by "resetting" to current schema 【发布时间】:2020-03-03 06:34:09 【问题描述】:

我们已经接管了一个旧的(3 年)Symfony 3.3 项目,该项目使用教义迁移 1.0 包来处理迁移。不幸的是,迁移脚本已经在没有人注意到的情况下被破坏了一段时间,因此您无法在不检查现有数据库的情况下从源代码构建新版本。

我想解决这种情况,以便运行composer doctrine:migrate 本质上只是运行一个虚拟脚本来创建当前架构的样子。我将如何做到这一点,以便在现有架构上运行时不会中断?

我想我会按照这些思路做一些事情:

    检查一个干净的项目(带有错误的旧迁移) 获取生产数据库转储 将生产数据库架构转储到 SQL 文件中 删除旧迁移 创建一个版本号与错误迁移中的“当前”/最高版本号相同的迁移文件 运行迁移

作为最后一步,通过删除数据库、导入生产数据库转储然后运行migrate 来验证这是否确实有效,以验证没有任何中断。我只是不确定如何在 Doctrine 包的上下文中执行此操作(我是 php 新手),即使在查阅了文档之后(似乎并未涵盖这种情况)。

【问题讨论】:

我曾经使用 Pomm 检查器执行此操作,并使用 Postgres pg_tap 扩展测试结果是否符合预期。 【参考方案1】:

我完全按照上面的草图进行了操作,而且效果很好。对于上下文,我有一组用于迁移脚本的元数据:

"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 日左右发现的。

这意味着不可能从新的源代码开始开发,使用教义:迁移:迁移命令,因为它很早就失败了。

同时,现有数据库包含有关过去执行了哪些迁移的元数据,因此任何修复都需要向迁移包发出信号,表明这些迁移已经/已经执行。

建议的解决方法是创建简单的“标记类”,仅满足发出迁移已完成/存在的信号的需求,然后将最后一个迁移类的内容替换为一个脚本,该脚本只需创建一个匹配任何生产数据库的当前状态是。

这是第 1 步。

将所有迁移脚本内容替换为空内容

这是修复的第 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)
    
    

删除助手

从 prod 转储架构

使用脚本清理架构

grep -v -- '--' production-schema-2020.sql \ 
  | awk 1 ORS=' ' \
  | sed -r -e 's/;\s+/; /g' > cleaned.sql

从 SQL 脚本生成 Doctrine PHP 语句

脚本:sed -e "s/^(.*);/\$this-&gt;addSql('\1');/" cleaned.sql &gt; cleaned-sql-to-php-statements.txt

将架构语句移到上次迁移中 基本上将cleaned-sql-to-php-statements.txt的内容复制粘贴到

删除临时文件

对生成的 PHP SQL 语句进行小幅调整和清理

【讨论】:

以上是关于通过“重置”到当前架构来修复损坏的迁移的主要内容,如果未能解决你的问题,请参考以下文章

如何修复“损坏的”交互式变基?

Drupal6-修复菜单链接,您可以通过SQL将它们重置为删除来删除它们

如何修复损坏的 SQL 视图

怎样修复损坏了的innodb 表

Exchange Server 2016管理系列课件39.新建本地移动请求

XFS 分区损坏修复方法