在Heroku上,在实例已经使用更改的模型代码重新启动后,Django syncdb / South迁移是否存在危险?

时间:2012-01-24 20:18:32

标签: django heroku django-south

在Heroku上,只要您推送新代码,即使尚未应用基础数据库架构添加/更改(通过syncdb或南迁移),Web服务实例也会重新启动。

在许多情况下,这可能只会导致无害的错误,并且很快就会运行syncdb / migrate。但是我担心在某些情况下,新代码可能会在迁移前数据库中进行意外更改。

安全抵御这种风险的正确方法是什么?

一种技术可能是将syncdb / migrate添加到Procfile中,以便在web重启之前运行。但是,在多个实例的情况下,或者甚至可能是一个旧的代码实例一直运行直到一个新的代码实例被知道的情况下,仍然存在一个问题的变体,其中代码是与具有不匹配架构的DB交谈。

是否存在“保留所有Web实例”功能(或常见的最佳做法),以便在没有网络流量的情况下完成迁移?

或者我过度担心在实践中可忽略不计的风险?

4 个答案:

答案 0 :(得分:9)

处理此类迁移的最安全的方法,Heroku或不,是严格采用兼容性方法与您的架构和代码:

  • 每个添加或变换架构更改必须向后兼容;
  • 必须在 之后执行每个破坏性架构更改已删除依赖它的代码;
  • 每次代码更改必须是:
    • 持久抵制尚未进行关联架构更改的可能性(例如,删除模型或模型上的字段)
    • 仅在执行关联的架构更改(在模型上添加模型或字段)之后才生成

如果您需要对模型进行重大转换,则此方法可能需要执行以下步骤:

  • 创建新的数据库表以保存新的模型结构,并部署该迁移
  • 使用新结构创建新模型,以及在旧模型更改时将更改从旧模型复制到新模型并部署该代码的代码
  • 执行迁移或代码操作以将所有旧模型数据复制到新模型
  • 更新代码库以使用新模型而不是旧模型,删除旧模型并部署该代码
  • 执行迁移以从数据库中删除旧模型结构

通过一些思考和计划,它也可以用于更激烈的变化:

  • 部署代码,完全消除对数据库某一部分的依赖,可能会用维护页面替换网站的那些部分
  • 部署迁移,进行大幅改动,不会出于任何原因使用上述双模型工作流程
  • 部署代码,使受影响的部分回归并支持新的模型结构

这可能很难组织,需要严格的纪律和对代码与数据库交互的深刻理解,但在实践中,确实允许进行大多数更改而不会导致停机时间超过服务器重启本身就强加了。

答案 1 :(得分:1)

看起来快速数据库转换是可行的方法,但它需要专用数据库。

http://devcenter.heroku.com/articles/fast-database-changeovers

或者,这是一个教程,用于将数据从一个数据库(例如,生产)复制到另一个数据库(例如,分段),执行模式/数据迁移(例如,使用django / south),然后切换应用程序以使用新更新的数据库实例。

http://devcenter.heroku.com/articles/migrating-data-between-plans

似乎合理,但如果有大量数据则可能会很慢。

答案 2 :(得分:1)

推荐的方法是:

  • 将新功能的数据库更改添加到现有代码
  • 使现有代码与新架构兼容
  • 部署
  • 将新功能添加到代码库
  • 部署

这意味着当代码开始需要时,您的数据库更改已经到位。

然而....

这有几个问题。首先,我知道没有任何开发商店有足够的组织能够处理这个问题,因为功能只是专门建立,其次是你并没有真正保存任何东西。

一般来说,除非您对大型数据库进行大的更改,否则您的更改将花费很长时间才能应用,并且通常会在几秒钟内结束,开发人员可以在需要时非常愉快地发布重新启动等。用户可能会收到错误页面的风险。如果变化较大,您可以选择其他方法。一种是使用维护模式关闭网站几秒钟。

说实话,没有明确的方法可以很好地处理这个问题,因为根据定义,您的代码需要到位才能启动数据库更改。我发现解决问题的最好方法是分别查看每个更改,并根据具体情况计算每个更改的最平滑路径。

在暂存环境中排演部署可以降低部署失败的风险,并让您了解影响。

答案 3 :(得分:1)

Heroku最近发布了“buildpacks”,这些脚本是用于为应用程序设置环境的脚本,从管理依赖项到重新启动实例。从本质上讲,它是一个更全面的Procfile,您可以自定义。

您可以分叉Python buildpack并修改脚本以按您想要的顺序运行。将您运行的命令附加到syncdbbin/steps/django的末尾。提交并将此回购放在Github上。

不幸的是,到目前为止,无法修改现有Heroku应用程序的buildpack,因此您必须删除它并重新创建一个指向buildpack存储库的内容:

heroku create --stack cedar --buildpack git@github.com:...

这是最佳解决方案,因为它

  • 根本没有任何费用
  • 不要求您将代码调整为Heroku
  • 仅每个部署同步一次数据库

希望这有帮助。