目录

一、简介

二、核心概念

1、Schema History Table

2、Migration

3、Versioned migrations

三、集成 SpringBoot

1、pom文件中引入依赖

2、application.yml配置

3、sql 脚本编写

四、初始化数据库

五、注意事项


一、简介

Flyway是一款开源的数据库版本管理工具,使用简单,应用无侵入。与 Liquibase 相比,由于 Flyway 面向sql,因此更直观清晰,对于我们来说,轻便的 Flyway 是一个更好的选择,两者相比一言以蔽之:

  • 面向 SQL,选择 Flyway
  • 不面向 SQL,选择 Liquibase

二、核心概念

1、Schema History Table

Flyway 对数据库进行版本控制的方式,是在指定数据库中创建一张表,即 Schema History Table(默认为 flyway_schema_history),记录由 Flyway 所执行的 sql 脚本状态。
表中字段解释:

  • installed_rank:执行序号
  • version:版本
  • script:sql脚本文件
  • checksum:类似文件md5值,用来检查 migration 在执行过后是否发生了变化,如果发生了变化,会导致这个版本以及后续版本的 migration 无法执行
  • success:是否执行成功,1成功,0失败

2、Migration

Flyway 将每一个数据库脚本称之为:migration,migration 可以是 SQL 文件,也可以是 Java 类,默认的查找 migration 的路径为 classpath:db/migration,对应 SQL 文件可放置在 src/main/resources/db/migration 下,Java 类可放置在 src/main/java/db/migration 下。flyway 支持三种类型的migration:

  • Versioned migrations:最常用的 migration,可以简单的理解为数据库升级脚本
  • Undo migrations:数据库版本回退脚本,可为对应版本的常规 versioned migration 进行回退操作,此功能为收费功能,社区版无法使用
  • Repeatable migrations:可重复执行的 migration,例如create or replace脚本,会在所有的 versioned migration 都执行过后再进行执行,即当脚本 checksum 改变时重新执行

所有的 migration 都需要遵守命名规范:

上面的配置已经设置了 baseline-on-migrate 为 true(默认 false),即已经告诉 Flyway 执行 migration 的时候是存在基线的,这样就不会报出数据库表不存在的错了。因此不管你的数据库是否非空,都能顺利运行,唯一的区别是第一个 sql 脚本文件的执行

拿上面这张图的 V1.0__init_database.sql 脚本来说,如果数据库为空,则默认会执行;反之则会把它作为基线,跳过执行下一个版本

数据库非空情况下 flyway_schema_history 表记录:

数据库为空情况下 flyway_schema_history 表记录:

四、初始化数据库

SpringBoot 集成完 Flyway 之后,数据库的创建同样需要作为程序启动即执行,否则项目复用时仍然需要先创建数据库再启动程序,不是很智能,部分代码如下:

public void initDataBase() {        try {            String databaseName = properties.getDatabaseName();            if (StringUtils.isEmpty(databaseName)) {                databaseName = JdbcUrlUtils.findDatabaseName(datasourceUrl);                log.debug("尝试获取spring.datasource.url中的数据库名称...url:{},name:{}", datasourceUrl, databaseName);            }            String jdbcUrlTmp = datasourceUrl.replace(SLASH+databaseName,BLANK);            SingleConnectionDataSource dataSourceTmp = new SingleConnectionDataSource(jdbcUrlTmp,username,password,true);            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceTmp);            String executeSql = String.format(properties.getCreateSchemaSql(), databaseName);            jdbcTemplate.execute(executeSql);            log.info("执行初始化库的sql,sql:{}", executeSql);        } catch (Exception e) {            log.error("校验数据库失败!", e);        }    }

在抽象初始化数据库这部分代码作为组件时,有一点需要注意,如果你的项目有使用 Mybatis-plus 框架,不建议采用自动配置的方式初始化bean,会出现 mp 的自动配置类执行顺序始终比自定义配置类快,可以采用 InitializingBean 和 BeanPostProcessor

五、注意事项

1、脚本文件如果已经执行过,便不要在进行任何更改,如果需要修改请通过新增一个新的 sql 脚本文件来达成;否则修改一个已经执行过的脚本,会导致 Flyway 校验失败(还原该脚本可以解决)
2、sql 脚本有错误,执行失败后进行修改,再次执行报错,理由同1,此时需要删除 flyway_schema_history 中对应版本的约束然后重新执行
3、增量脚本里的 sql 尽量保证可以多次执行