使用 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.url
、spring.datasource.username
、spring.datasource.password
。这就是我的应用程序连接到数据库的方式。我可以为插件重复使用此属性吗?
@ieXcept 是的,你可以!!
@ieXcept 我可以推荐我正在开发的这个插件吗?包括一个生成迁移的命令github.com/tom-power/spring-boot-flyway-migrate【参考方案3】:
当数据库迁移失败时,迁移在架构历史表(i.e flyway_schema_history)
中标记为失败,表示可能需要手动清理数据库。但如果数据库支持 DDL 事务,则迁移会自动回滚,并且架构历史表中不会记录任何内容。 PostgreSQL
、Amazon Redshift
、MS SQL
是少数支持 DDL 事务的数据库,而 Oracle Database
、MySQL
、MariaDB
、Amazon 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中创建H2+flyway测试数据库?