Django:在 Heroku 上部署时如何保持代码和数据库同步?

Django: How to keep code and database sync'ed when deploying on Heroku?

假设我们有一个名为 Alpha 的 Django 项目。在将 Django 项目部署到 Heroku 之前,开发人员在他们的开发环境中进行 Alpha 测试。 Procfile 可能类似于:

release: python manage.py migrate
web: python -m gunicorn wsgi:application

当开发人员尝试部署新版本的 Alpha 时,该项目将与其迁移文件一起交付(按照建议)。在部署结束时,Heroku 会执行 release 语句 python manage.py migrate 对数据库进行所有相关更改。因为发布是整个部署过程的一部分,如果失败则不会部署新代码。

但是...虽然代码将恢复到部署前的状态(如预期的那样),但对 Heroku 数据库的潜在更改将是永久性的。例如,我们假设新版本有三个新的迁移:

前两次迁移正确执行,数据库也相应更改。它们也被添加到数据库 table django_migrations。然而,最后一个包含一个问题(例如,它定义了阶段数据不遵守的约束)。

在这种情况下,Heroku 上的代码(/migrations/models.py)和 Heroku 上的数据库现在严重不同步:事实上,数据库反映了迁移不同步的变化甚至出现在代码库中。这会产生各种各样的问题。

如何防止在这个谓词中发现自己并确保代码和数据在阶段和生产上始终 100% 同步?

Post 脚本

Heroku 的文档中包含以下片段:

Use transactions for database migrations

When performing a database migration, always use transactions. A transaction ensures that all migration operations are successful before committing changes to the database, minimizing the possibility of a failed partial migration during the release phase. If a database migration fails during the release phase (i.e., the migration command exits with a non-zero status), the new release will not be deployed. If transactions were not used, this could leave the database in a partially migrated state. We suggest using heroku run, rather than the release phase, to make schema/data corrections.

正如您引用的文档所说,在事务中进行迁移是个好主意。 Django does this by default with databases that support it.

真是个好主意

但这只对一次迁移的范围有帮助:如果迁移 0013 像您的示例一样失败,它引入的更改将被回滚。迁移 00110012 引入的更改不会被撤销。

要反向迁移 00110012,您必须 roll back manually,例如

python manage.py migrate myapp 0010

但是如果您的部署失败,您的应用程序将是 运行 之前的版本,您不能简单地 heroku run 认为——Heroku 没有 0011 的迁移文件和 0012.

这很可能,至少部分是 Heroku 文档所说的

We suggest using heroku run, rather than the release phase, to make schema/data corrections.

如果删除迁移发布阶段命令,您可以像这样开始部署:

git push heroku main
heroku run python manage.py migrate

如果迁移失败,只需反转最后两次迁移,然后roll back to the previous release:

heroku run python manage.py migrate myapp 0010
heroku releases:rollback

作为额外的预防措施,请考虑在开始升级之前将您的应用放入 maintenance mode。这将防止用户在您的网站可能处于不一致状态时与您进行交互,例如在部署之后但在应用迁移之前。