我正在构建一个使用 hibernate 和 mysql 和 tomcat 的 web 应用程序。随着产品的发展,我不断被要求提供新功能,这通常意味着需要更改数据模型。
我现在正在做的是将数据库的所有关键数据导出到一个平面文件中。关闭数据库和服务器,重新配置数据库以匹配新的休眠映射和 mysql 表和列,以编程方式导入保存的数据以适应新的数据模型,然后重新启动服务器。
还有什么推荐的?
您可以使用dbdeploy或类似的增量数据库工具来允许您在升级之间添加增量。
他们为您跟踪数据库的版本,并在您开发时为您所做的每个模型更改添加一个新的 Delta。当您升级生产服务器时,您对它运行 dbdeploy 并确定数据库处于什么状态,然后只应用必要的升级。
这意味着您永远不必导出和重新导入数据 - 您只需将更新应用到现有数据模型 - 这将大大加快您的部署时间,但仍然会出现一些中断。
建议您在升级前转储数据库 - 因为如果出现问题,您可以快速回滚。
编辑
我找到了关于 EngineYard 如何使用迁移实现零停机时间的链接——他们使用 Ruby,但方法类似于我在此处概述的方法。
如果您对零停机时间部署感兴趣,那么有很多方法可以解决这个问题。我发现这篇博客文章概述了实现这一目标的不同策略。
基本要点是您在单独的时间对主要应用程序进行数据库升级,并确保数据库具有可为空的列,并且代码可以调整以使列神秘地出现或消失。
作者为不同的技术提供了一些策略——但随后承认用 hibernate 来做这件事有点繁琐:
Hibernate – 让它运行起来可能有点麻烦,尤其是在删除列的情况下。您通常会为持久类创建通用接口,并使用多个版本的实现类。在初始化 SessionFactory 之前,您可以通过使用模式或结果集元数据来决定将哪组类连接到 Hibernate。Java 中的其他持久性技术存在更糟糕的问题,尤其是许多喜欢在启动时检测类的字节码的 JPA 风格。
这是一篇很棒且有趣的文章,我建议您全部阅读。
(Facebook 和 Yahoo 不使用 Hibernate!)
从用户的角度来看,为了呈现零停机时间,它通常涉及使用受负载均衡器保护的应用程序集群 - 因此您可以将每个应用程序从策略中取出并升级它,而无需用户在重新启动时尝试访问它。你必须考虑会话粘性、数据源一致性和各种其他的东西——但主要的是它不是魔法。
没有别的推荐了。如果这种方式对你有用,那很好。您还可以使用 alter 语句来使您的数据库模式演变。如果由于大量数据而无法再从平面文件导出和导入数据,请使用临时表来迁移数据等。但有时,必须以某种方式迁移数据。