使用 Spring Boot 进行 Flyway 修复

Posted

技术标签:

【中文标题】使用 Spring Boot 进行 Flyway 修复【英文标题】:Flyway repair with Spring Boot 【发布时间】:2016-09-24 13:23:33 【问题描述】:

我不太明白当在 Spring Boot 项目中使用 Flyway 迁移失败时我应该做什么。

我只需在 pom.xml 中添加 Flyway 依赖项即可激活 Flyway。一切正常。当我启动 Spring Boot 应用程序时,我的数据库脚本被迁移。

但是我的一个脚本中有一个错误,并且我的最后一次迁移失败了。现在,当我尝试迁移时,出现“迁移校验和不匹配”。通常,我会运行mvn flyway:repair,但由于我使用的是 Spring Boot,所以我不应该使用 Flyway Maven 插件。那我该怎么办?

【问题讨论】:

我会说手动运行flyway repair 因为更改以前的 sql 文件应该是非常特殊的。但看起来类路径中的 sql 文件和本地的 sql 文件之间的校验和不匹配... 但是,就像我说的,在使用 Spring Boot 时,您不应该使用 Flyway 插件。 不,但是通过使用flyway,您不需要更改现有的sql文件!特别是如果它们已经在 prod db 上执行。您应该只在每次更改时添加新的 SQL 文件。我可以理解为什么 spring-boot 不支持这一点:它应该保持手动操作,当然不应该默认......(忽略对 SQL 已经运行的任何更改) 好的,但是你如何测试你的 SQL 脚本呢?手动?还是使用 Flyway 插件? 两者。我的开发环境中基本上有一个“测试数据库”,我可以随时刷新:mvn flyway:clean flyway:migrate。您也可以使用 flyway 命令行。 【参考方案1】:

有几种方法可以对数据库执行修复。我个人更喜欢简单的 SQL 语句。

SQL 语句:

只需删除迁移失败的行。之后,您可以再次运行迁移。

直接运行flyway

您可以在本地安装 Flyway 并在控制台中运行 flyway repair

使用 Flyway Maven 插件

将Flyway Maven Plugin 添加到您的pom 并运行mvn flyway:repair。我认为这与 Spring Boot 的概念并不矛盾。

扩展 Spring Boot

Spring Boot 会调用Flyway.migrate() 来执行数据库迁移。如果您想要更多控制权,请提供实现 FlywayMigrationStrategy@Bean

FlywayMigrationStrategy 中,您可以从flyway 调用迁移或修复方法。更多信息请访问Spring Boot Reference Guide。

我认为应用程序中的FlywayMigrationStrategy 不是修复数据库的正确位置。失败的迁移是一个例外,应该在应用程序之外进行处理。

【讨论】:

flyway-maven-plugin 可以从我的 Spring Boot application.properties 文件中读取数据源属性吗? @Daniel Käfer 在迁移开始前使用 FlywayCallback 清理 schema_version 中的数据(即删除失败的迁移)怎么样? @DharmvirTiwari 我认为这不是一个好主意。如果第一次失败,第二次也会失败。你必须做一些事情让它工作,你可以手动删除 schema_version 表中的行。【参考方案2】:

Flyway Maven 插件

只是将此信息添加到@Daniel 的回答中

1.

      ...
        <plugin>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-maven-plugin</artifactId>
            <version>4.1.0</version>
            <configuration>
                <url>jdbc:mysql://localhost:3306</url>
                <user>root</user>
                <password>root</password>
                <schemas>
                    <schema>[your_schema]</schema>
                </schemas>
            </configuration>
        </plugin>
      ...

2.

mvn flyway:clean

3.

mvn flyway:repair

PS.:如果第 2 步和第 3 步不起作用,请更改顺序。

更多关于 maven 目标的信息:https://flywaydb.org/documentation/maven/

【讨论】:

flyway-maven-plugin 可以从我的 Spring Boot application.properties 文件中读取数据源属性吗? @ieXcept 您希望将什么样的信息添加到您的属性文件中? 我已经添加了spring.datasource.urlspring.datasource.usernamespring.datasource.password。这就是我的应用程序连接到数据库的方式。我可以为插件重复使用此属性吗? @ieXcept 是的,你可以!! @ieXcept 我可以推荐我正在开发的这个插件吗?包括一个生成迁移的命令github.com/tom-power/spring-boot-flyway-migrate【参考方案3】:

当数据库迁移失败时,迁移在架构历史表(i.e flyway_schema_history) 中标记为失败,表示可能需要手动清理数据库。但如果数据库支持 DDL 事务,则迁移会自动回滚,并且架构历史表中不会记录任何内容。 PostgreSQLAmazon RedshiftMS SQL 是少数支持 DDL 事务的数据库,而 Oracle DatabaseMySQLMariaDBAmazon Aurora 不支持 DDL 事务。

如果迁移条目失败,有几个选项可以修复它(仅适用于不支持 DDL 事务的数据库),如 @daniel-käfer 所述。我想添加另一种(可能更简单的方法)来处理失败的迁移。

flyway 支持多个callbacks,afterMigrateError 就是其中之一。如果我们添加一个名为 afterMigrateError.sql 的 sql 文件,那么它将在每次失败的 migrate 运行后执行。因此,我们可以简单地使用 sql 命令在数据库迁移文件夹(resources/db/migration)的默认位置创建一个文件afterMigrateError.sql,以从flyway_schema_history 表中删除失败的迁移。

sql命令afterMigrateError.sql可以如下:

DELETE IGNORE FROM flyway_schema_history WHERE success=0;

此命令查找表flyway_schema_history(如果存在),否则不会进行任何更改。然后它只查找具有success 列和0 条目的行(实际上,如果迁移失败会发生这种情况,所有成功的迁移都将在成功列中具有值1),然后删除这些条目。现在,我们可以简单地更改我们最新的迁移文件并更正它并再次运行。

【讨论】:

这个方法很棒!比手动输入maven命令方便多了,非常感谢!【参考方案4】:

如above所说的在本地安装flyway,将目录更改为安装然后运行(以H2为例):

./flyway -url=jdbc:h2:/Users/mugo/dev/h2/das-boot -user=sa -password= repair

【讨论】:

【参考方案5】:

您可以通过代码声明以下 bean 来实现。

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

【讨论】:

这非常有效,因为我无法访问数据库本身。干杯! 添加了这个。谢谢很好的提示。 @ConditionalOnProperty(value = "custom.spring.flyway.repair-on-migrate", havingValue = "true") @Primary 注意:当从 spring-boot 1.5 升级到 2.x 时,这还不够,因为 Flyway 5 不向后兼容 3.0 架构(哦,具有讽刺意味!)。 This question 提供 spring-boot 升级的答案。 "只需删除迁移失败的行。之后您可以再次运行迁移。":如果迁移包含 DDL 语句并且 DBMS 不支持 DDL 事务,则此方法不起作用。迁移可能在中间失败,从头开始重新运行可能会导致其他错误。

以上是关于使用 Spring Boot 进行 Flyway 修复的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Boot 不适用于 Flyway

在 Spring Boot 应用程序中使用 Flyway 进行多数据源迁移

Flyway 和 Spring Boot 集成

如何在spring boot中创建H2+flyway测试数据库?

在 Spring Boot 应用程序上使用 Flyway 时如何在 H2 中加载初始数据?

带有用户名和密码的 Zonky + Spring Boot + Postgres + Flyway