为了随着时间的推移发展数据库模式,我们需要进行数据库迁移。 Rails 为我们提供了强大的功能来做到这一点。众所周知,Rails 中的每次迁移都包含在 DDL 事务中(至少对于 Postgres 而言)。这意味着如果某些迁移中途失败,则与此迁移相关的所有更改都将回滚。但是,我注意到,如果我们有多个迁移,并且其中一个迁移失败,那么之前的迁移将不会回滚。这在生产部署方面是一个问题,因为新的部分迁移可以部分完成。
假设我们有 5 个新的迁移想要部署到生产中。
migration_1.rb
migration_2.rb
migration_3.rb
migration_4.rb
migration_5.rb
如果例如在
migration_4.rb
上发生错误,则所有之前的迁移(migration_1.rb
、migration_2.rb
、migration_3.rb
)将不会回滚。
遇到这种情况我该如何处理?
我有一个想法,通过这样的方式取消代码部署并回滚以前的迁移
rails db:rollback STEP=n # n - number of migrations that managed to pass successfully
但是我还有一个问题——如果回滚过程中出现错误怎么办?
我推荐的最佳实践:每次部署仅进行一次迁移。迁移在一个事务中运行,因此如果单个迁移失败,假设整个部署也随之失败(因此您最终不会部署依赖于失败迁移的代码更改),也不会造成任何损害。
但是,如果一个成功而下一个失败,您的数据库将最终处于您不希望的状态,并且您将必须手动回滚。
如果您的多个迁移彼此相关并且需要作为一个部署,只需将它们重构为单个迁移文件即可。如果它们属于可以单独部署的单独功能,请改为这样做。
关于回滚失败 - 您的迁移应该“始终”能够回滚,这应该是您开发过程的一部分。例如,如果您迁移数据,请确保将其迁移回 down
版本。
db:migrate:redo
。在进行迁移之前始终这样做是一个很好的做法。