独立于数据库的数据迁移

Posted

技术标签:

【中文标题】独立于数据库的数据迁移【英文标题】:database independent data migration 【发布时间】:2018-04-07 23:30:48 【问题描述】:

我的目标是为现有应用程序启用架构和数据迁移。

这种问题好像被问过很多次了,不过我觉得和我的要求和情况不同。

由于我在这个领域缺乏经验,请允许我先列出应用程序的架构和我的假设。

架构

该应用程序是一个多用户企业桌面应用程序,其后端服务器可以持久保存到任何主要数据库(mysql、Postgresql、SQL Server、Oracle DB 等)。假设数据库在本地并由我们的客户维护。

使用的技术栈是相当常见的 Hibernate+Spring+RMI/JMS-Combo。

目前,迁移由服务器通过以下方式完成:

在服务器启动时,它会检查最新的预期架构版本 如果大于当前版本,则开始迁移到下一个版本,直到 current==latest:
    创建新数据库 加载(整个)最新架构(带有大量 CREATE TABLE ... 的 SQL 脚本) 迁移数据(在 Java 类中使用 2 个 JDBC 连接到新旧模式) 加载(全部)最新约束(包含大量 ALTER TABLE ... 的 SQL 脚本)

此迁移缓慢且仅向前迁移。但这很简单。问题是,到目前为止,数据迁移中的模式脚本和查询一直使用 MySQL 语法和功能。

请注意,迁移数据我的意思是:后端服务器将数据从旧模式复制到新模式,并在必要时对其进行转换。 此外,迁移过程会在我们的客户内部自动启动。这意味着,我们只能控制 JDBC 连接,但不能直接访问数据库,也不能了解正在使用的特定数据库(MySQL、SQL Server 等)。

目标是用独立于数据库的迁移方案替换或扩充此迁移方案。

假设和研究

*** 1 2 3 4 5 6 7:回答状态以使用 Hibernate 的内置功能。但是,文档声明这不是production ready。此外,AFAICT,所有答案都与仅架构迁移有关。

Liquibase:使用自定义 DSL(在 XML/JSON/YAML/等中)以允许独立于数据库的仅模式迁移

DBUnit:使用自定义 XML-DSL 捕获数据库状态的快照。 无法重新创建架构版本 1 到版本 2 的快照

flyway: 原则上与 Liquibase 相同。但不是独立于数据库的,因为 SQL 脚本用于迁移。

JOOQ:基于 JDBC 的 Java 中独立于数据库的 Query-DSL。与 Criteria API 相当,但没有 JPA 的缺点。原则上应该允许,但是,有助于架构迁移

HQL、JPQL、Criteria API 等 JPA 查询语言是不够的,因为

    无法引用实体管理器未映射的表。例如。联接表、元数据和审计表。 需要为映射保留所有版本的实体类的副本。

问题

我意识到,就目前这个问题而言,它将被视为基于意见而被驳回。

但是,我不一定要寻找这个问题的具体解决方案(我怀疑对于如此复杂的问题空间是否存在明确的解决方案),而是要验证我的假设。

也就是说,是不是真的,那个

Liquibase 和 Flyway 主要关注架构迁移,而数据迁移留给读者作为练习? 为了让 Flyway 支持多个不同的数据库,是否需要为每个数据库复制迁移脚本? 总的来说,问题在企业 Java 中仍未解决?

即使我将 Liquibase/Flyway 与 JOOQ 结合使用,我也看不到如何执行数据迁移,因为 Liquibase/Flyway 迁移数据库就地。旧数据库被破坏,并有机会将旧数据转换为新模式。

感谢您的关注!

【问题讨论】:

【参考方案1】:

让我们稍微分解一下。你是对的,这在很大程度上是基于意见的,但这是我在我的经验中注意到的。

Liquibase 和 Flyway 主要关注架构迁移,数据迁移留给读者练习?

您可以使用 liquibase 和 flyway 进行数据迁移。这是我经常做的事情。以我想将 User 表拆分为 User 和 Address 表为例。我会编写一个迁移脚本,它基本上只是一个 sql 文件,以创建新的 Address 表并将所有相关数据复制到其中。

为了让 Flyway 支持多个不同的数据库,是否需要为每个数据库复制迁移脚本?

可能,flyway 和 liquibase 最好被视为数据库版本控制工具。如果我的应用程序需要版本 10 的数据库,这些工具将帮助我达到这一点。同样,迁移脚本只是基本的 .sql 文件。如果您正在使用一些 mysql 特定的函数,那么这些函数只会进入迁移脚本,它们不会在 sql server 上工作

总的来说,企业 Java 中独立于数据库的数据迁移问题仍未解决?

呃,我不确定这个。我同意这是一个问题,但实际上它并不是一个大问题。在过去 8 年多的时间里,我只写过 ansi sql。它应该随处可移植。所以理论上,我们可以将这些应用程序提升到不同的数据库中。 JPA 和各种实现有助于解决这些差异。根据你的项目是如何构建的,比如说一个应用程序,它的所有业务逻辑都在实现特定的 sql 函数中,那么这将是一个令人头疼的问题。如果您将数据库用于 CRUD,并且我认为这就是您应该使用它的全部,那么这没什么大不了的。

说了这么多,我想你可能对 flyway 和 liquibase 有错误的想法。就像我之前所说的,它们并不是真正的“迁移工具”,而是数据库版本控制工具。通过订购的特定 sql 迁移脚本列表,我可以保证我的数据库在任何版本的状态。我不确定这些工具是否可以用来将基于旧 SQL Server 的应用程序“迁移”到基于 PostGres 的应用程序中。

【讨论】:

非常感谢您抽出宝贵时间分享您的经验! 您如何/如何处理更复杂的数据转换?例如。转换包含 XML 的表值或更改数据类型?我不确定您是否理解正确;目标不是从旧版 SQL Server 迁移到其他 SQL Server。但是要同时支持多个数据库。抱歉,如果您已经清楚了。 您可以在 liquibase 或 flyway 等工具中处理更复杂的数据转换,就像在 sql 中一样。这些工具的核心只是一个按特定顺序运行的 sql 迁移列表。更改数据类型可能看起来像 1. 创建具有所需类型的新列 2. 将数据从旧列/类型迁移到新列 3. 清理旧列 顺便说一句,在正在运行的系统中做这些事情是非常复杂的。这个book可能对你有用

以上是关于独立于数据库的数据迁移的主要内容,如果未能解决你的问题,请参考以下文章

如何处理使用相同数据库的两个独立 laravel 项目的迁移?

Docker数据持久化与容器迁移

模型独立学习:多任务学习与迁移学习

InnoDB--------独立表空间平滑迁移

迁移如何应用于数据库? [关闭]

数据迁移的套路