如何从第3航道直接升级到第5航道 [英] How to upgrade from flyway 3 directly to flyway 5

查看:64
本文介绍了如何从第3航道直接升级到第5航道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

致力于在许多生产环境中由许多客户端部署的产品.它至少包含一个Spring Boot应用程序.

Working on a product that is deployed by many clients in many production environments. It includes at least one Spring Boot app.

我们已经使用flyway进行数据库模式迁移.从Spring Boot 1.5.x升级到2.0.x已将我们的飞行版本从3.x升级到5.x.

We've used flyway for db schema migrations. Upgrading from Spring Boot 1.5.x to 2.0.x has bumped our flyway version from 3.x to 5.x.

Spring Boot迁移指南只是说要在引导升级之前先升级到flyway 4.但是,这将需要我们所有的客户进行一次中间升级,然后才能升级到最新版本.

The Spring Boot migration guide simply says to upgrade to flyway 4 before the boot upgrade. However, this would require all of our customers to do an intermediate upgrade before being able to upgrade to the latest.

因此,问题是:将如何从第3航道直接升级到第5航道?

So, the question is: How would you upgrade from flyway 3 directly to flyway 5?

推荐答案

如果我不是地球上最后一个仍要从3升级到5的人.

In case I'm not the last person on the planet to still be upgrading from 3 to 5.

问题:

我希望升级对项目中的其他开发人员而言是透明的,并且在实时应用程序上进行升级时不需要任何特殊的部署说明,所以我执行了以下操作.

I wanted the upgrade to be transparent to other developers on the project as well as not requiring any special deployment instructions when upgrading on the live applications, so I did the following.

我看了第4版如何处理升级:

I had a look at how version 4 handled the upgrade:

  • 在Flyway.java中,将调用MetaDataTableImpl.upgradeIfNecessary
  • upgradeIfNecessary检查version_rank列是否仍然存在,如果存在,则从org/flywaydb/core/internal/dbsupport/YOUR_DB/
  • 运行一个名为upgradeMetaDataTable.sql的迁移脚本.
  • 如果执行了upgradeIfNecessary,则Flyway.java运行DbRepair调用repairChecksumsAndDescriptions
  • In Flyway.java a call is made to MetaDataTableImpl.upgradeIfNecessary
  • upgradeIfNecessary checks if the version_rank column still exists, and if so runs a migration script called upgradeMetaDataTable.sql from org/flywaydb/core/internal/dbsupport/YOUR_DB/
  • If upgradeIfNecessary executed, then Flyway.java runs a DbRepair calling repairChecksumsAndDescriptions

这很容易手动进行,但要使其透明.该应用程序是一个Spring应用程序,但不是Spring Boot应用程序,因此,当我让flyway在应用程序启动时通过依赖于flyway bean的LocalContainerEntityManagerBean构造自动在应用程序启动时运行迁移,这将迁移称为init方法(在此解释 Flyway Spring JPA2集成-可以保持架构验证吗? ),因此引导顺序为:

This is easy enough to do manually but to make it transparent. The app is a spring app, but not a spring boot app, so at the time I had flyway running migrations automatically on application startup by having LocalContainerEntityManager bean construction dependent on the flyway bean, which would call migrate as its init method (explained here Flyway Spring JPA2 integration - possible to keep schema validation?), so the order of bootstrapping would be:

Flyway bean created -> Flyway migrate called -> LocalContainerEntityManager created

解决方案:

我将引导程序的顺序更改为:

I changed the order of bootstrapping to:

Flyway bean created -> Flyway3To4Migrator -> LocalContainerEntityManager created

如果需要,Flyway3To4Migrator将在其中执行schema_table更改,如果升级发生,请运行修复,然后始终运行flyway.migrate以继续迁移.

where Flyway3To4Migrator would perform the schema_table changes if needed, run the repair if the upgrade happened, and then always run flyway.migrate to continue the migrations.

@Configuration
public class AppConfiguration {

    @Bean
    // Previously: @DependsOn("flyway")
    @DependsOn("flyway3To4Migrator")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        ...
    }

    // Previously: @Bean(initMethod = "migrate")
    @Bean
    public Flyway flyway(DataSource dataSource) {
        ...
    }
}

@Component
@DependsOn("flyway")
public class Flyway3To4Migrator {
    private final Log logger = LogFactory.getLog(getClass());
    private Flyway flyway;

    @Autowired
    public Flyway3To4Migrator(Flyway flyway) {
        this.flyway = flyway;
    }

    @PostConstruct
    public void migrate() throws SQLException, MetaDataAccessException {
        DataSource dataSource = flyway.getDataSource();

        boolean versionRankColumnExists = checkColumnExists(dataSource);
        if (versionRankColumnExists) {
            logger.info("Upgrading metadata table to the Flyway 4.0 format ...");
            Resource resource = new ClassPathResource("upgradeMetaDataTable.sql", getClass().getClassLoader());
            ScriptUtils.executeSqlScript(dataSource.getConnection(), resource);
            logger.info("Metadata table successfully upgraded to the Flyway 4.0 format.");

            logger.info("Running flyway:repair for Flyway upgrade.");
            flyway.repair();
            logger.info("Complete flyway:repair.");
        }

        logger.info("Continuing with normal Flyway migration.");
        flyway.migrate();
    }

    private boolean checkColumnExists(DataSource dataSource) throws MetaDataAccessException {
        return (Boolean) JdbcUtils.extractDatabaseMetaData(
            dataSource, dbmd -> {
                ResultSet rs = dbmd.getColumns(
                        null, null,
                        "schema_version",
                        "version_rank");
                return rs.next();
            });
    }
}

一些注意事项:

  • 有时,我们将删除多余的Flyway3To4Migrator类,并将配置恢复为原来的状态.
  • 我从v4 Flyway jar复制了我的数据库的相关upgradeMetaDataTable.sql文件,并将其简化为表名等.如果需要,可以从flyway中获取模式和表名.
  • SQL脚本周围没有事务管理,您可能想要添加它
  • Flyway3To4Migrator调用flyway.repair(),它比DbRepair.repairChecksumsAndDescriptions()稍微多一点,但是我们很高兴接受数据库在运行之前必须处于良好状态

这篇关于如何从第3航道直接升级到第5航道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆