如何避免使用 Liquibase 搬起石头砸自己的脚

以前从未发生过,我们又来了!

在我们的下一个项目中,我们决定从一开始就使用 Liquibase 以避免将来出现问题。 事实证明,并非所有年轻的团队成员都知道如何正确使用它。 我举办了一次内部研讨会,然后我决定将其变成一篇文章。

本文包含有用的提示,并描述了使用关系数据库迁移工具(特别是 Liquibase)时可能陷入的三个最明显的陷阱。 专为初级和中级 Java 开发人员设计;对于更有经验的开发人员来说,它可能会对构建和重复最有可能已知的内容感兴趣。

如何避免使用 Liquibase 搬起石头砸自己的脚

Liquibase和Flyway是Java世界中解决关系结构版本控制问题的主要竞争技术。 第一个是完全免费的,在实践中它最常被选择使用,这就是 Liquibase 被选为该出版物的主角的原因。 但是,所描述的一些实践可能是通用的,具体取决于您的应用程序架构。

关系结构的迁移是应对关系数据存储灵活性弱的被迫方式。 在 OOP 时尚时代,使用数据库的风格意味着我们只需描述一次模式,就不会再次触及它。 但现实情况总是发生变化,并且经常需要对表结构进行更改。 当然,这个过程本身可能是痛苦和不愉快的。

我不会更深入地描述技术和向项目添加库的说明;关于这个主题已经写了很多文章:

此外,已经有一篇关于有用提示的优秀文章:

Советы

我想分享我的建议和评论,这些建议和评论是通过解决移民问题的汗水、鲜血和痛苦而诞生的。

1. 在开始工作之前,您应该熟悉以下最佳实践部分 在线 液化石油气

那里 描述了简单但非常重要的事情,如果没有这些,使用图书馆会让你的生活变得复杂。 例如,管理变更集的非结构化方法迟早会导致混乱和破坏迁移。 如果不同时对数据库结构和服务逻辑进行相互依赖的更改,则很有可能导致红测试或环境损坏。 此外,官方网站上的Liquibase使用建议中包含了与主要迁移脚本一起开发和测试回滚脚本的条款。 嗯,文章中 https://habr.com/ru/post/178665/ 有关于迁移和回滚机制的代码示例。

2. 如果开始使用迁移工具,不要允许手动更正数据库结构

俗话说:“一旦宝莹,永远宝莹。” 如果应用程序的基础开始由 Liquibase 管理,任何手动更改都会立即导致不一致的状态,并且更改集的信任级别变为零。 潜在的风险包括恢复数据库需要花费几个小时;在最坏的情况下,服务器会死机。 如果您的团队中有一位“老派”DBA 架构师,请耐心且深思熟虑地向他解释,如果他只是根据自己对条件 SQL 开发人员的理解来编辑数据库,事情将会多么糟糕。

3.如果变更集已经推送到存储库中,请避免编辑

如果另一个开发人员拉取并应用了一个变更集,稍后将对其进行编辑,那么当他在启动应用程序时收到错误时,他肯定会用友善的话语记住您。 如果编辑变更集以某种方式泄漏到开发中,您将不得不遵循修补程序的滑坡。 问题的本质在于通过散列和验证更改——这是 Liquibase 的主要机制。 编辑变更集代码时,哈希值会发生变化。 仅当可以从头开始部署整个数据库而不丢失数据时,才可以编辑变更集。 在这种情况下,重构 SQL 或 XML 代码反而可以使工作变得更轻松,并使迁移更具可读性。 一个例子是这样的情况:在应用程序开始时,源数据库的架构在团队内达成一致。

4. 如果可能的话,验证数据库备份

到这里,我想,一切都清楚了。 如果突然迁移不成功,一切都可以退回来。 Liquibase有一个用于回滚更改的工具,但回滚脚本也是由开发人员自己编写的,它们可能与主变更集的脚本以相同的概率出现问题。 这意味着在任何情况下安全地进行备份都是有用的。

5. 如果可能的话,在开发中使用经过验证的数据库备份

如果这不违背合同和隐私,数据库中没有个人数据,它的重量也没有两个太阳那么重——在实时迁移服务器上使用它之前,您可以检查它在开发人员的机器上如何工作并计算几乎 100% 的迁移过程中的潜在问题。

6. 与团队中的其他开发人员沟通

在组织良好的开发过程中,团队中的每个人都知道谁在做什么。 事实上,情况通常并非如此,因此,如果您准备对数据库结构进行更改作为任务的一部分,建议您另外通知整个团队。 如果有人同时进行更改,您应该仔细组织。 工作结束后与同事的交流是值得的,而不仅仅是开始时。 变更集的许多潜在问题可以在代码审查阶段得到解决。

7. 想想你在做什么!

这似乎是不言而喻的建议,适用于任何情况。 然而,如果开发人员再次分析他所做的事情以及它可能产生的影响,许多问题是可以避免的。 处理迁移总是需要额外的关注和准确性。

陷阱

现在让我们看看如果不遵循上述建议,您可能会陷入的典型陷阱,以及您到底应该做什么?

情况 1:两个开发人员试图同时添加新的变更集

如何避免使用 Liquibase 搬起石头砸自己的脚
Vasya 和 Petya 希望在彼此不知情的情况下创建变更集版本 4。 他们对数据库结构进行了更改,并使用不同的变更集文件发出了拉取请求。 建议采用以下作用机制:

如何决定

  1. 不知何故,同事们必须就他们的变更集的执行顺序达成一致,例如,应该首先应用 Petin。
  2. 有人应该将第二个添加到自己身上,并用版本 5 标记 Vasya 的变更集。这可以通过 Cherry Pick 或巧妙的合并来完成。
  3. 更改后,您一定要检查所采取操作的有效性。
    事实上,Liquibase 机制将允许您在存储库中拥有两个版本 4 变更集,因此您可以将所有内容保留原样。 也就是说,您只需对版本 4 进行两次更改,并使用不同的名称。 使用这种方法,以后导航数据库版本会变得非常困难。

此外,Liquibase就像霍比特人的家园一样,保守着许多秘密。 其中之一是 validCheckSum 键,它出现在 1.7 版本中,允许您为特定变更集指定有效的哈希值,而不管数据库中存储的是什么。 文档 https://www.liquibase.org/documentation/changeset.html 说如下:

添加一个被认为对此变更集有效的校验和,无论数据库中存储了什么。 主要在您需要更改变更集并且不希望在已运行变更集的数据库上引发错误时使用(不是推荐的过程)

是的,是的,不建议执行此程序。 但有时候,强大的光系魔法师也掌握着暗系魔法

情况二:依赖数据的迁移

如何避免使用 Liquibase 搬起石头砸自己的脚

假设您无法使用实时服务器的数据库备份。 Petya 创建了一个变更集,在本地进行了测试,并完全相信自己是对的,向开发人员提出了拉取请求。 为了以防万一,项目负责人澄清了 Petya 是否检查过它,然后添加了它。 但开发服务器上的部署却下降了。

事实上,这是可能的,没有人能幸免。 如果对表结构的修改以某种方式与数据库中的特定数据相关联,就会发生这种情况。 显然,如果 Petya 的数据库只填充测试数据,那么它可能无法覆盖所有问题案例。 例如,当删除一张表时,发现其他表中的外键记录与被删除的表中的记录相关。 或者当更改列类型时,结果发现并非 100% 的数据可以转换为新类型。

如何决定

  • 编写将在迁移时使用一次的特殊脚本,并将数据转换为正确的形式。 这是解决应用迁移后将数据传输到新结构问题的通用方法,但在特殊情况下,之前也可以应用类似的方法。 当然,这条路径并不总是可行,因为在实时服务器上编辑数据可能很危险,甚至具有破坏性。
  • 另一种困难的方法是编辑现有的变更集。 困难在于,所有已经以其现有形式应用的数据库都必须恢复。 整个后端团队很可能被迫从头开始在本地部署数据库。
  • 最通用的方法是将数据问题转移到开发人员的环境中,重新创建相同的情况并向损坏的情况添加新的变更集,这将规避该问题。
    如何避免使用 Liquibase 搬起石头砸自己的脚

一般来说,数据库的组成与生产服务器数据库越相似,迁移问题出现严重问题的可能性就越小。 当然,在将变更集发送到存储库之前,您应该多次考虑它是否会破坏任何内容。

情况三、Liquibase投产后开始使用

假设团队负责人要求 Petya 将 Liquibase 包含在项目中,但该项目已经投入生产并且有现有的数据库结构。

因此,问题在于,在任何新服务器或开发人员计算机上,必须从头开始重新创建这些表,并且现有环境必须保持一致状态,准备好接受新的变更集。

如何决定

还有几种方法:

  • 第一个也是最明显的是有一个单独的脚本,在初始化新环境时必须手动应用该脚本。
  • 第二个不太明显,在另一个 Liquibase 上下文中进行 Liquibase 迁移,然后应用它。 您可以在此处阅读有关 Liquibase Context 的更多信息: https://www.liquibase.org/documentation/contexts.html。 一般来说,这是一个有趣的机制,可以成功地用于测试等。
  • 第三条路径由几个步骤组成。 首先,必须为现有表创建迁移。 然后必须将它应用到某个环境中,从而获得它的哈希和。 下一步是在我们的非空服务器上初始化空的 Liquibase 表,并且在包含变更集使用历史记录的表中,您可以手动放置有关“已应用”变更集的记录,其中变更集已存在于数据库中。 因此,在现有服务器上,历史倒计时将从版本 2 开始,并且所有新环境都将表现相同。
    如何避免使用 Liquibase 搬起石头砸自己的脚

情况 4. 迁移变得巨大并且没有时间完成

在服务开发之初,通常使用 Liquibase 作为外部依赖项,所有迁移都在应用程序启动时处理。 然而,随着时间的推移,您可能会偶然发现以下情况:

  • 迁移变得巨大并且需要很长时间才能完成。
  • 需要在分布式环境中进行迁移,例如同时在多个数据库服务器实例上进行迁移。
    在这种情况下,应用迁移时间过长将导致应用程序启动时超时。 此外,单独对每个应用程序实例应用迁移可能会导致不同的服务器不同步。

如何决定

在这种情况下,您的项目已经很大,甚至可能是一个成熟的项目,Liquibase 开始充当单独的外部工具。 事实上,Liquibase 作为一个库被编译成 jar 文件,并且可以作为项目内的依赖项或独立工作。

在独立模式下,您可以将迁移的实施留给 CI/CD 环境或系统管理员和部署专家来负责。 为此,您需要 Liquibase 命令行 https://www.liquibase.org/documentation/command_line.html。 在此模式下,可以在执行所有必要的迁移后启动应用程序。

结论

事实上,在进行数据库迁移时可能存在更多陷阱,其中许多需要创造性的方法。 重要的是要了解,如果正确使用该工具,大多数陷阱都是可以避免的。 具体来说,我必须以不同的形式处理列出的所有问题,其中一些问题是我的错误造成的。 当然,大多数情况下发生这种情况是由于疏忽,但有时是由于犯罪分子无法使用该工具。

来源: habr.com

添加评论