在 Heroku 上,在实例已经使用更改的模型代码重新启动后,Django syncdb / South 迁移是不是存在危险?
Posted
技术标签:
【中文标题】在 Heroku 上,在实例已经使用更改的模型代码重新启动后,Django syncdb / South 迁移是不是存在危险?【英文标题】:On Heroku, is there danger in a Django syncdb / South migrate after the instance has already restarted with changed model code?在 Heroku 上,在实例已经使用更改的模型代码重新启动后,Django syncdb / South 迁移是否存在危险? 【发布时间】:2012-02-18 02:16:41 【问题描述】:在 Heroku 上,只要您推送新代码,Web 服务实例就会重新启动...即使尚未应用基础数据库架构添加/更改(通过 syncdb 或南迁移)。
在许多情况下,这可能只会导致无害的错误,直到 syncdb/migrate 很快运行。但我担心在某些情况下,新代码可能会在迁移前数据库中进行意外更改,从而导致一半的工作。
防范这种风险的正确方法是什么?
一种技术可能是将 syncdb/migrate 添加到 Procfile 中,以便它在 web 重新启动之前运行。但是,在多个实例的情况下,或者甚至在一个旧代码实例一直运行直到一个新代码实例已知的那一刻的情况下,仍然存在代码是问题的变体与架构不匹配的数据库交谈。
是否有“保留所有 Web 实例”功能(或常见的最佳实践)让迁移在没有 Web 流量的情况下完成?
或者我是否过度担心在实践中可以忽略不计的风险?
【问题讨论】:
+1 好问题。我有完全相同的问题,并认为这是一个需要避免的严重风险。如果 syncdb/migrate 顺利,您的站点将关闭不到一分钟。但是,如果由于某种原因失败了,您的网站将会关闭,直到您能够解决它... 我也有同样的问题。实际上,我的站点在关闭时发生了,因为我的南迁移没有成功。幸运的是,我能够使用“heroku rollback”命令回滚更改。 我会推荐一个暂存实例来“练习”迁移,然后再在您的实际生产站点上尝试迁移。 devcenter.heroku.com/articles/multiple-environments 我同意 - 维护模式 (heroku maintenance:on
) 可能就足够了,但在生产中我有点担心自己 - 我有一个暂存环境,但我认为这样做的好处提供与此问题正交
【参考方案1】:
看起来快速数据库转换是可行的方法,但它需要一个专用数据库。
http://devcenter.heroku.com/articles/fast-database-changeovers
或者,这里有一个教程,用于将数据从一个数据库(例如,生产)复制到另一个数据库(例如,staging),进行架构/数据迁移(例如,使用 django/south),然后切换应用程序以使用新更新的数据库实例。
http://devcenter.heroku.com/articles/migrating-data-between-plans
看起来很合理,但如果有大量数据,可能会很慢。
【讨论】:
【参考方案2】:推荐的方法是这样的:
将新功能的数据库更改添加到现有代码中 使现有代码与新架构兼容 部署 将新功能添加到您的代码库中 部署这意味着当代码开始需要它们时,您的数据库更改已经到位。
但是....
这有几个问题。首先,我知道没有任何开发商店组织得足够好,能够处理这个问题,因为功能只是临时构建的,其次,你并没有真正节省任何东西。
一般来说,除非您对大型数据库进行重大更改,否则您的更改不会花费很长时间来应用,并且通常会在几秒钟内结束,开发人员可以在需要时非常高兴地发出重新启动等问题。用户可能会收到错误页面的风险。如果更改较大,您有一些替代方案。一种是使用维护模式关闭网站几秒钟。
说实话,没有明确的方法可以很好地处理这个问题,因为根据定义,您的代码需要在适当的位置才能开始您的数据库更改。我发现解决问题的最佳方法是单独查看每个更改,并根据具体情况为每个更改制定最平滑的路径。
在暂存环境中预演部署将降低部署失败的风险,并让您了解影响。
【讨论】:
【参考方案3】:处理这种性质的迁移的最安全方法,无论是否有 Heroku,都是严格采用与您的架构和代码兼容的方法:
每个附加或转换架构更改都必须向后兼容; 必须在删除依赖它的代码之后执行每个破坏性架构更改; 每次代码更改必须是: 能够抵御尚未进行关联架构更改的可能性(例如,删除模型或模型上的字段)或 仅在执行相关架构更改(在模型上添加模型或字段)后进行如果您需要对模型进行重大转换,此方法可能需要以下步骤:
创建一个新的数据库表来保存您的新模型结构,并部署该迁移 使用新结构创建新模型,并在旧模型更改时将更改从旧模型复制到新模型的代码,并部署该代码 执行迁移或代码操作,将所有旧模型数据复制到新模型中 更新您的代码库以使用新模型而不是旧模型,删除旧模型并部署该代码 执行迁移以从数据库中删除旧模型结构经过一些思考和计划,它也可以用于更剧烈的变化:
部署完全消除对数据库部分依赖的代码,大概用维护页面替换站点的这些部分 部署进行重大更改的迁移,无论出于何种原因,上述双模型工作流都无法使用 部署代码,使受影响的部分恢复并支持新的模型结构这可能很难组织起来,需要严格的纪律和对代码与数据库交互的深刻理解,但在实践中,它确实允许在不超过停机时间的情况下进行大多数更改服务器重新启动本身强加。
【讨论】:
【参考方案4】:Heroku 最近发布了“buildpacks”,这是他们用来为您的应用程序设置环境的脚本,从管理依赖项到重新启动实例。本质上,它是一个更全面的Procfile
,您可以对其进行自定义。
您可以 fork Python buildpack 并修改脚本以按您想要的顺序运行。将您运行到syncdb
的命令附加到bin/steps/django
的末尾。提交并将这个 repo 放到 Github 上。
不幸的是,目前无法修改现有 Heroku 应用程序的 buildpack,因此您必须将其删除并重新创建一个指向您的 buildpack 存储库的文件:
heroku create --stack cedar --buildpack git@github.com:...
这是最好的解决方案,因为它
完全不花钱 不需要您将代码适应 Heroku 每次部署只同步一次数据库希望这会有所帮助。
【讨论】:
以上是关于在 Heroku 上,在实例已经使用更改的模型代码重新启动后,Django syncdb / South 迁移是不是存在危险?的主要内容,如果未能解决你的问题,请参考以下文章
数据库更改时,Heroku 部署的 Django 网页不会更新