Laravel 迁移事务

2022-08-30 15:42:27

在开发时,我在laravel中遇到了很多迁移问题。

我创建了一个迁移。当我完成创建它时,在迁移过程中有一个小错误(例如,外键约束),使“php artisan migrate”失败。他确实告诉我错误在哪里,但随后迁移会进入不一致的状态,在错误发生之前对数据库所做的所有修改都是如此,而不是下一个修改。

这使得当我修复错误并重新运行迁移时,第一个语句失败,因为列/表已经创建/修改。然后,我知道的唯一解决方案是转到我的数据库并手动“回滚”所有内容,这需要更长的时间。

migrate:rollback 尝试回滚以前的迁移,因为当前未成功应用。

我还尝试将所有代码包装到DB::transaction()中,但它仍然不起作用。

有什么解决方案吗?或者我只需要继续用手把东西卷回来?



编辑,添加一个示例(不编写架构生成器代码,只是某种伪代码):
Migration1:

Create Table users (id, name, last_name, email)

迁移 1 执行正常。几天后,我们制作了《迁移 2》:

Create Table items (id, user_id references users.id)
Alter Table users make_some_error_here

现在将发生的事情是,迁移将调用第一个语句,并将使用他的外键向用户创建表项。然后,当他尝试应用下一个语句时,它将失败。

如果我们修复make_some_error_here,则无法运行迁移,因为它创建的表“项”。我们无法回滚(也无法刷新,也无法重置),因为我们无法删除表用户,因为表项中存在外键约束。

然后,继续的唯一方法是转到数据库并手动删除表项,以便在一致状态下进行迁移。


答案 1

这不是Laravel的限制,我敢打赌你使用MYSQL,对吧?

正如MYSQL文档在这里所说

某些语句无法回滚。通常,这些语句包括数据定义语言 (DDL) 语句,例如创建或删除数据库的语句,创建、删除或更改表或存储例程的语句。

我们有泰勒·奥特韦尔本人的建议在这里说:

我最好的建议是每次迁移执行一次操作,以便迁移保持非常精细。

-- 更新 --

不用担心!

最佳实践说:

你永远不应该做出重大改变。

这意味着,在一个部署中,您可以创建新表和字段,并部署使用它们的新版本。在下一个部署中,您将删除未使用的表和字段。

现在,即使您在这两个部署中的任何一个中都遇到问题,如果迁移失败也不必担心,工作版本无论如何都会使用功能数据结构。通过每次迁移的单一操作,您可以立即发现问题。


答案 2

我正在使用MySql,但我遇到了这个问题。

我的解决方案取决于您的方法完全符合您在后面所做的工作。down()up()

这就是我要去的:

try{
    Schema::create('table1', function (Blueprint $table) {
        //...
    });
    Schema::create('tabla2', function (Blueprint $table) {
        //...
    });
}catch(PDOException $ex){
    $this->down();
    throw $ex;
}

因此,如果出现问题,则会自动调用该方法并再次引发异常。down()

与其使用迁移之间,不如在此尝试之间进行迁移transaction()


推荐