【问题标题】:Can Liquibase or Flyway handle multi non-linear versioning scenario?Liquibase 或 Flyway 可以处理多非线性版本控制方案吗?
【发布时间】:2013-05-08 08:45:56
【问题描述】:

这是一个艰难的过程。

  1. v1.1 有一个索引为 i 的表。
  2. v2.1 也包含此表和索引。

发现了一个错误,我们在v1.1.0.1 中更改了代码,因此决定删除索引。
我们为v2.1v2.1.0.6创建了相应的补丁。

客户应用了补丁v1.1.0.1,几周后升级到v2.1(没有补丁6)

由于v2.1 代码库在索引方面表现更好,我们有一个“损坏”的应用程序。

  • 我不能强迫我的客户应用最新的补丁。
  • 我不能强迫开发人员避免这种情况。

Liquibase 或 Flyway 可以处理这种情况吗?

【问题讨论】:

  • 如果补丁更改会创建一个列,也会发生同样的情况,但这次使用 v2.1 运行时,应用程序真的会被破坏,而不仅仅是性能不佳。

标签: liquibase flyway


【解决方案1】:

我想这类问题更具组织性,而不是特定于工具的。如果您支持多个版本(一个分支 1.0 和一个较新的 2.0)并为两者提供补丁(这是完全合法的方法 - 不要误会我的意思),您可能必须为所有这些版本提供升级说明,也许还有一个矩阵,显示您可以从哪个版本转到(以及您不能做什么)。

我刚刚升级了 Atlassian 的 Jira Bugtracker 的旧版本,不得不发现他们确实提供了所有版本的升级说明。

这意味着从一个版本到下一个版本最终到达最新版本(我使用的是 4.x 版本并想升级到最新的 5.x 版本)并遵守其间的所有升级说明。 (顺便说一句,我跳过了所有这些并将其设置为全新安装以避免这种情况。)

只是为了给您一个印象,下面是一个显示所有这些升级说明的页面: https://confluence.atlassian.com/display/JIRA/Important+Version-Specific+Upgrade+Notes

所以我想如果有人想从版本1.1.0.1 升级到2.1 并在升级说明中说明需要应用它,我想你可以提供一个重新创建索引的小脚本。

既然您询问 liquibase(或 flyway)是否可以支持这一点,也许提一下 liquibase(我只知道 liquibase)有一个名为 preConditions 的东西会有所帮助。这意味着您可以根据存在(例如)索引<indexExists> 的事实来运行变更集(resp. sql)。

如果索引丢失,这可能有助于重新创建索引。

但是由于 2.1 版本已经发布(在知道索引可能会在未来的错误修复中被删除之前),因此没有机会将此功能添加到 2.1 版本的升级过程中。

【讨论】:

  • 我认为这在技术上是可行的。如果 liquibase 有一个在当前变更集中不存在的 chanelog 条目(即发生降级),则意味着该条目应该回滚。但是,我认为这样的功能可能很难处理,因此不太实用。
  • 很遗憾,我们无法强制客户升级到最新版本,他们有正当理由。
【解决方案2】:

Liquibase 可以很好地处理跨分支的 drop index 更改,但是由于您要从包含代码的版本(drop index 更改)变为不希望您最终会出现损坏的应用程序状态的版本。

使用 liquibase,更改完全相互独立,并且独立于任何版本控制。您可以将 liquibase 更改日志视为更改的有序列表,以使每个更改都具有唯一标识符。当您进行更新时,liquibase 会依次检查每个更改以查看它是否已运行,如果没有运行则运行它。

任何“版本控制”都纯粹在您的代码库和分支方案中,liquibase 不在乎。

假设您从 1.1.0 版本开始,如下所示:

  • 换一个
  • 改变 b
  • 改c

当您部署 1.1.0 时,客户数据库将知道更改 a、b 和 c 已运行。

您的更新日志文件末尾有带有新更改集的 v2.1,所以它看起来像:

  • 换一个
  • 改变 b
  • 改c
  • 改变x
  • 改变你
  • 改变z

并且所有 2.1 客户数据库都知道应用了 a、b、c、x、y、z。

当您使用删除索引的变更集 d 创建 1.1.0.1 时,您最终会在 1.1.0.1 分支中看到此变更日志:

  • 换一个
  • 改变 b
  • 改c
  • 改变d

但是当您将 1.1.0.1 客户升级到 2.1 时,liquibase 只会将 (a,b,c,x,y,z) 的已定义变更集与 (a,b,c,d) 的已知变更集进行比较,运行 x,y,z。它不关心 d 是否已经运行了变更集,它对此无能为力。

liquibase diff 支持可以用作一些健全性检查,并且能够报告与某些“正确”数据库相比缺少索引,但这不是您在生产部署中通常会做的事情场景。

【讨论】:

  • 在@AdiB 问题中,他说他不能强迫他的客户申请2.1.0.1 所以change d(正在删除索引)将不会被应用。因此有一个代码库2.1(它认为索引在那里)和一个运行1.1.0.1(删除索引或change d)的数据库。即使客户为2.1 运行 liquibase 变更集,也不会重新创建已删除的索引。他将不得不强迫客户也申请2.1.0.1。如果我没有弄错这个问题,我仍然认为这是一个组织问题。
  • 我明白了,我以为他是说他可以让 1.1.0 的客户升级到 1.1.0.1,但不能升级到 2.1.0.6。重新阅读问题,我发现他们正在从 1.1.0.1(包含变更集 d 删除索引)到 2.1.0(没有变更集 d)。使用 Liquibase,当您升级到 2.1.0 时,它并不关心变更集 d 不在变更日志中,即使它在数据库中标记为已运行并且不会尝试恢复索引。他将在 2.1 中没有索引,这是一个“损坏的”更新。我会更新我的答案。
【解决方案3】:

答案可能有点晚,但我会分享我的经验。我们在项目中也遇到了同样的问题。我们是通过以下方式处理的:

由于我们项目中的版本不经常发布,因此我们在 liquibase 中特别标记了每个变更集 context。该值是确切的版本迁移(如 v6.2.1-v6.2.2)。我们通过 jndi 属性将值传递给 liquibase,因此客户可以指定它们。因此,在升级期间,客户负责为每次升级的迁移范围设置正确的值。 Liquibase 上下文可以接受值列表。所以最后,上下文看起来像这样:

context=v5.1-5.2,v5.3-5.3.1,v5.3.1-5.4,v6.2.1-v6.2.2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 2013-01-07
    • 2013-05-19
    相关资源
    最近更新 更多