如果你正在使用Django ORM或Alembic之类的模式管理工具,那你在某个时候就需要运行迁移。将迁移作为应用程序启动的一部分来运行听起来是很诱人的——例如,当你使用Docker时,你会有一个首先运行迁移,然后启动应用程序的入口点。
但是,将迁移与服务器启动相结合可能会导致一些问题,从数据库损坏到宕机,尤其是当你开始规模化部署并获得更多用户时。
因此,在本文中,我将解释为什么将它们结合是一个问题,以及你可以做些什么。
在应用程序启动时进行迁移不是一个好主意
当你在开发一个新应用程序时,在应用程序启动时进行数据库迁移是很自然的事情。当你在开发新特性时,你会对模式和代码进行一些更改,重新启动你的测试服务器,并立即同步最新的模式和代码。
但是开发环境与生产环境是不同的,这可能会导致问题。
问题1:并行迁移会导致数据库损坏
在开发环境中,你通常会启动一个服务器,但在生产环境中,你可能会启动多个服务器。因此,现在不是一个进程执行模式迁移,而是多个进程尝试同时执行多个相同的模式迁移。
根据你的数据库,你正在使用的迁移工具以及你正在进行的迁移类型、并行模式升级可能会以多种方式损坏你的数据库。
你不会想要一个损坏的数据库!
问题2:思想上的结合会导致宕机
如果你总是在应用程序启动时进行模式升级,那么你最终还会在思想上集结合模式迁移和代码升级。特别是,你将开始假设你只运行带有最新模式的新代码。
为什么这个假设是一个问题?从最常见到最不常见的情况来说:
有时你需要回滚一个损坏的代码升级。如果你假设你总是有带有新模式的新代码,那么最终可能会出现新代码被损坏的情况,但是你不能轻松地回滚到旧代码,因为你已经进行了一个不可逆转的模式更改。
为了最小化升级时的停机时间,你希望有一个可以同时运行应用程序新旧版本的短暂时刻。如果你的模式迁移破坏了旧代码,你就不能这样做。
要捕获新代码中的bug,你可能需要执行一个金丝雀部署(canary deploy)。也就是说,只升级许多进程中的一两个进程,然后看看它们是否会崩溃。
另一种选择:将模式迁移与代码升级分离
你希望模式迁移与代码升级分开进行:
因此,你可以运行单个迁移,而无需担心并行性。
为了减少停机风险,你可以选择将旧代码与新模式一起运行。
第一个需求可以通过使模式迁移成为一个不同的命令来解决——稍后我们将讨论如何为Docker实现这个命令。或者你可以使用一个使用锁定来确保不会发生并行性的迁移工具,例如Flyway。
零停机时间模式迁移
第二个需求需要更多的工作,所以你可能会选择不为运行时间要求不那么繁重的应用程序做这些工作。本质上,你希望将模式迁移结构化为纯附加的,至少在短期内是这样。
例如,代替更改列类型,你可以添加一个新列,并使用触发器来确保两个变量保持同步。然后,一旦你确定永远不需要返回旧代码,你就可以运行进一步的模式迁移(同样,不需要升级代码)来清除不再需要的列。
一般流程为:
从模式S迁移到模式S+1,只进行一些添加更改。
随着时间的推移,将一些进程从应用程序版本V升级到V+1。
最终所有的东西都在V+1上,并且你永远不会期望回滚到V上。
最后,从模式S+1迁移到模式S+2,现在你可以对V+1不再使用的任何东西进行有破坏性的模式更改。
当然,你仍然需要做一些工作来处理数据库锁之类的问题。这里是一个PostgreSQL的概述,作为一个起点。
使用Docker进行分离
如果你使用Docker打包应用程序,那你就不需要为模式迁移和应用程序构建单独的镜像。相反,你可以构建一个这样的单个镜像:
按默认设置运行应用程序。
可以选择在应用程序启动之前进行模式迁移,这对于使用镜像进行开发和测试非常有用。
可以被告知在应用程序启动时单独运行迁移。
注意:在讨论的特定主题之外,本文中的Dockerfile并不是最佳实践的示例,因为额外增加的复杂性会模糊本文的要点。
想要一个最佳实践Dockerfile并构建系统?请查看我的可用于生产的Python容器产品。
首先,创建一个默认情况下运行你的入口点脚本的Dockerfile:
只有在你设置了环境变量时,入口点脚本才会运行数据库迁移:
所以现在在默认情况下,迁移不会发生:
如果你设置了DEV_MODE环境变量,你将同时执行迁移和应用程序启动:
你可以手动运行迁移,与运行服务器分开:
开发不是生产
在本例中,我们关注的是数据库迁移,但是还有一个更广泛的观点: 在开发和测试环境中运行良好的配置和使用模式在生产环境中并不总是运行良好。
请注意其他需要区分这两者的情况。
学习如何快速构建可用于生产的Docker映像——请阅读针对Python的Docker打包指南的其余部分。
英文原文:https://pythonspeed.com/articles/schema-migrations-server-startup/
译者:浣熊君( ・᷄৺・᷅ )
领取专属 10元无门槛券
私享最新 技术干货