如何处理无效的先前有效的 Flyway 迁移

Posted

技术标签:

【中文标题】如何处理无效的先前有效的 Flyway 迁移【英文标题】:How to deal with previously valid Flyway migrations that became invalid 【发布时间】:2020-08-05 11:20:18 【问题描述】:

我有一个 Spring Boot 应用程序,它使用 Flyway 在 Postgres 中进行数据库迁移。

现在大约 4 岁了,所以我们说的是 Flyway 4.0.3、Spring Boot 1.3.x 和 Postgres 9.x。版本可能会升级,但我想在此之前修复任何现有问题。

与此同时,Postgres 已升级到高于 9.x 的版本。不幸的是,一些现有的迁移已经过时,因为它们包含不推荐使用的语法。因此,现在使用新数据库(即在开发环境中)启动应用程序会导致这些迁移失败。在生产中这很好,因为这些迁移已经应用并且不会再次应用。

我很好奇在这方面的最佳做法是什么。我不能只修复现有迁移中的语法,因为这会导致生产环境中的校验和失败。我知道repair 是一个东西,但是我不确定它是如何工作的以及如何将它与 Spring Boot 一起使用。

失败的 SQL:

UPDATE config
SET (description) = 'my description'
WHERE ...

正确的 SQL:

UPDATE config
SET description = 'my description'
WHERE ...

错误:

Message    : ERROR: source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression

编辑 2020 年 4 月 24 日 Spring Boot 解决方案:

Grant Fitchey 在下面发布了关于如何使用 repair 的正确答案后,我将具体说明我是如何使用 Spring Boot 做到这一点的。我刚刚创建了一个 FlywayMigrationStrategy 的 bean,它调用 repair 在它调用 migrate 之前:

@Bean
public FlywayMigrationStrategy cleanMigrateStrategy() 
    return flyway -> 
        flyway.repair();
        flyway.migrate();
    ;

将其部署到生产环境时,在启动期间,Postgres 中 schema_versions 表中的校验和已修复。在另一个版本中,我将再次删除 flyway.repair(); 行,否则显然这会产生应用无效迁移的风险。

【问题讨论】:

您能举一些迁移失败的例子吗?不推荐使用的语法不应导致错误..... 我已经编辑了我的问题@CodeScale 【参考方案1】:

您正在寻找修复选项。我不知道如何通过spring boot直接调用它,但是documentation is here。这应该完全符合您的要求。

因此,在这种情况下,第一步是修复迁移,以便它们在开发环境中正确执行。现在开发应该没问题了,flyway 应该可以成功迁移了。

在生产环境中,您现在应该会收到验证错误,因为校验和不同。 Flyway repair 将“修复”模式历史表,以便它存储的校验和与磁盘上的新校验和匹配,因此 flyway 验证再次通过。 具体来说,flyway repair 所做的是使模式历史记录表与您在磁盘上的内容相匹配。它将应用迁移的所有校验和更新为磁盘上的校验和(因此,只有在您确信更改相同时才使用它)。它还会从表中删除所有失败的迁移条目(同样,只有在您自己清理数据库后才使用它)。

【讨论】:

是的,我是这么认为的,这就是我在问题中提到它的原因。但是我不清楚如何在 Spring Boot 中使用它。不能说我找到了很好的文档。 是的,对不起。我很了解 Flyway,但 Spring Boot 是个谜。 你能不能——不管 Spring Boot 是什么——准确描述在这种特定情况下对我来说什么修复? IE。我有一个已经应用迁移的生产环境,以及一个新的开发环境,但情况并非如此。如何将我的迁移更改为正确的语法并使用修复使其适用于所有环境? 啰嗦了,所以我要把它添加到答案中。如果您还有其他问题,请告诉我。 谢谢!我也让它与 Spring Boot 一起工作。我会接受您的回答,并将 Spring Boot 部分添加到我的问题中。

以上是关于如何处理无效的先前有效的 Flyway 迁移的主要内容,如果未能解决你的问题,请参考以下文章

db关闭时如何处理flyway

如何处理删除基于光标的分页中的先前元素?

当click_action被发送到应用程序的先前版本尚未添加意图过滤器的情况下如何处理?

如何处理无效的流标头异常:00000001?

改造2如何处理有时无效有时非无效的服务器响应

如何处理 MongoDB / Morphia 中的查询迁移?