如何处理 Rails 部署过程中迁移失败的问题?

How to deal with failed migrations during deployment in Rails?

提问人:Taras 提问时间:8/10/2023 更新时间:8/12/2023 访问量:140

问:

为了随着时间的推移发展数据库架构,我们需要进行数据库迁移。Rails 为我们提供了强大的功能来做到这一点。众所周知,Rails 中的每次迁移都封装在一个 DDL 事务中(至少对于 Postgres 而言)。这意味着,如果某些迁移在中途失败,则与此迁移相关的所有更改都将回滚。但是,我注意到,如果我们有多个迁移,并且其中一个失败,那么以前的迁移将不会回滚。这在生产部署方面是一个问题,因为迁移的新部分可以部分完成。

假设我们有 5 个新的迁移,我们想要将其部署到生产环境中。

migration_1.rb
migration_2.rb
migration_3.rb
migration_4.rb
migration_5.rb

例如,如果发生错误,则不会回滚所有以前的迁移 (, , )。migration_4.rbmigration_1.rbmigration_2.rbmigration_3.rb

我应该如何处理这种情况?

我有一个想法,通过这样的方式取消代码部署并回滚以前的迁移

rails db:rollback STEP=n # n - number of migrations that managed to pass successfully

但是我还有另一个问题 - 如果在回滚过程中发生错误怎么办?

Ruby-on-Rails 数据库 部署 后端 rails-migrations

评论

4赞 David 8/10/2023
IMO,避免迁移问题的最简单方法是使您的架构向后兼容,并将它们与代码更改分开部署(例如,首先部署模型删除,然后迁移以删除表,或先添加新列,然后部署相关更改)。在这种情况下,如果迁移失败且代码回滚,则应用将正常运行。这是你可以申请的东西吗?
1赞 dbugger 8/10/2023
修复迁移 4 并重新部署。前三个都成功了,你为什么要回滚它们?
0赞 Taras 8/10/2023
@dbugger 下面是一个示例。如果我将旧代码保留在生产环境中,那么某些功能可能会损坏,因为前三个迁移之一可能包含重命名列。因此,我想还原前三个迁移以保留旧列名称并且不破坏任何内容。
0赞 Taras 8/10/2023
@dbugger 另一方面,尽管有一些中断的迁移,但我仍然可以部署新代码,但是在我修复和部署这些迁移之前,依赖于未完成的迁移的功能将被破坏。
1赞 dbugger 8/10/2023
这就是为什么你有一个 QA 环境来测试你的部署,并验证你的迁移是否按预期工作,并在它们不按预期工作时修复它们。比构建一些机制来回滚成功的迁移要简单得多。

答:

2赞 Thilo 8/12/2023 #1

我建议的最佳做法是:每次部署只进行一次迁移。迁移在事务中运行,因此,如果单个迁移失败,则不会造成任何损害,假设整个部署都失败了(因此您最终不会部署依赖于失败迁移的代码更改)。

但是,如果一个成功而下一个失败,则数据库最终将处于您不希望的状态,您将不得不手动回滚。

如果多个迁移相互关联,并且需要作为一个迁移进行部署,只需将它们重构为单个迁移文件即可。如果它们属于可以单独部署的单独功能,请改为执行此操作。

关于回滚失败 - 迁移应始终能够回滚,这应该是开发过程的一部分。例如,如果迁移数据,请确保将其迁移回版本中。down

测试这一点的一种简单方法是在本地使用。在提交迁移之前,最好始终这样做。db:migrate:redo

评论

0赞 Taras 8/14/2023
这听起来很有趣,但我现在无法将这种方法集成到我的项目中。但无论如何,谢谢你的想法。