• 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打印出来了
  • 相关阅读:
    Flask入门学习教程
    Qt-day3
    操作系统面试知识点
    网络面试知识
    业务单表 读写缓慢 如何优化?
    Qt编写ERP库存库房发货电子看板
    SSM+智能社区服务的设计与实现 毕业设计-附源码221512
    分享超高清多机位现场直播间搭建方案
    RPA案例|云扩助力保险行业开启超自动化运营新阶段
    速卖通,国际站测评补单用什么环境,买家账号不会被风控,F号
  • 原文地址:https://blog.csdn.net/yx444535180/article/details/126171960