目录
一、简介
二、核心概念
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 尽量保证可以多次执行