• Flyway报错源码分析——Validate failed: Migrations have failed validation


    一、异常信息

    今天早上启动项目,突然出现了如下异常,百度了一下没有合适的解决方案,决定从源码入手,看看能不能解决。

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[spring-context-5.3.4.jar:5.3.4]
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:582) ~[spring-context-5.3.4.jar:5.3.4]
    	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
    	at com.zhx.realpro.CloudAlarmApplication.main(CloudAlarmApplication.java:33) ~[classes/:na]
    Caused by: org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
    	at org.flywaydb.core.Flyway$1.execute(Flyway.java:172) ~[flyway-core-7.1.1.jar:na]
    	at org.flywaydb.core.Flyway$1.execute(Flyway.java:164) ~[flyway-core-7.1.1.jar:na]
    	at org.flywaydb.core.Flyway.execute(Flyway.java:538) ~[flyway-core-7.1.1.jar:na]
    	at org.flywaydb.core.Flyway.migrate(Flyway.java:164) ~[flyway-core-7.1.1.jar:na]
    	at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:66) ~[spring-boot-autoconfigure-2.4.3.jar:2.4.3]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.4.jar:5.3.4]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.4.jar:5.3.4]
    	... 19 common frames omitted
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    二、异常分析

    根据错误信息,报的是FlywayValidateException异常,找到这个类打上断点在这里插入图片描述
    启动项目,查看调用链
    在这里插入图片描述
    找到了抛出异常的位置,在它前面的这行打上断点启动项目,因为是这个结果判断之后才抛出异常
    ValidateResult validateResult = doValidate(database, migrationResolver, schemaHistory, schemas, callbackExecutor, true);
    跟进这行去看

    ValidateResult validateResult = new DbValidate(database, schemaHistory, schemas, migrationResolver, configuration, ignorePending, callbackExecutor).validate();

    在这里插入图片描述
    validate方法里面,在Callable的call方法做校验,这块感觉有点过度设计了,没找到另起线程的好处。
    在这里插入图片描述
    migrationInfoService的refresh方法sql文件加载进来了,这块就不看了。接着往下进入List invalidMigrations = migrationInfoService.validate();
    在这里插入图片描述
    验证所有sql文件的checksum,如果sql文件是第一次执行,会产生一个checksum。之后改了sql文件的内容checksum的值就会发生改变,从而验证失败validateError就不会为空,那么invalidMigrations就会添加一条。进入migrationInfo.validate();
    在这里插入图片描述
    走到这块发现两个checksum不一致。跟进去resolvedMigration.checksumMatches
    在这里插入图片描述
    不一致就返回false
    在这里插入图片描述
    返回一个ErrorDetails,错误信息很详细,不过最终却没有输出,看看怎么回事,返回到DbValidate.DbValidate方法,call执行之后返回了result。
    在这里插入图片描述
    目前为止result里面还是有详细的错误信息的
    在这里插入图片描述
    校验失败的sql文件不为空就进入 validationError = new ErrorDetails(ErrorCode.VALIDATE_ERROR, "Migrations have failed validation");,这里的异常信息写死成“Migrations have failed validation”,导致更加详细的错误信息没有输出,记得老版本的flyway是有输出的。这样改了反而不直观。返回到Flyway.migrate
    在这里插入图片描述
    校验失败,抛出异常信息“ Migrations have failed validation”。

    三、解决方案

    前面已经讲到一般是由于sql文件在第一次执行之后发生了改变导致的。

    • 方案一:不要改动sql文件,增加新的sql文件去修改表
    • 方案二:直接将数据库表flyway_schema_history中的checksum改成新生成的checksum,但是不建议直接改库。估计也是这个原因,新版的flyway就不把新产生的checksum打印出来了
  • 相关阅读:
    CodeLite 16.0可以编译通过,但是在编辑器界面会显示找不到标准库头文件
    又“库”又“芯” | GBASE南大通用&海光信息打造联合解决方案
    Windows照片查看器无法查看某些照片的解决方案
    Java堆内存溢出问题分析和解决
    tf.GPUOptions
    安装PyCharm(最完整版)
    哈希表 | 三数之和、四数之和 | 用`双指针法`最合适 | leecode刷题笔记
    Redis典型应用之缓存
    Zookeeper、Kafka集群与Filebeat+Kafka+ELK架构、部署实例
    CTPN网络理解
  • 原文地址:https://blog.csdn.net/yx444535180/article/details/126171960