SpringBoot引入Flyway,及Flyway简单了解

Flyway 中的常用概念

Flyway 中的概念可查阅 官方文档,这里挑选一些重要的进行简单介绍。

Schema History Table

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

Migration

在 Flyway 中,所有对数据库的变动,均称为 migration,migration 可以是 SQL 文件,也可以是 Java 类。

默认的查找 migration 的路径为 classpath:db/migration,对应 SQL 文件可放置在 src/main/resources/db/migration 下,Java 类可放置在 src/main/java/db/migration 下。

Migration 可以是仅执行一次的(versioned),也可是重复执行的(repeatable)。

Versioned Migration

Versioned migration 包括版本号、描述和校验值(checksum,自动计算),命名方式如下:

SpringBoot引入Flyway,及Flyway简单了解_第1张图片

Versioned Migration

其中版本号必须全局(一个 Schema History Table 里)唯一,且默认情况下(可通过参数调整)版本号只能增加,不能在已经执行了高版本的 migration 之后再执行低版本的 migration。

版本号可以是数字加 . 的形式,例如下列都是合法的版本号:

1
001
5.2
1.2.3.4.5.6.7.8.9
205.68
20130115113556
2013.1.15.11.35.56
2013.01.15.11.35.56

checksum 用来检查 migration 在执行过后是否发生了变化,如果发生了变化,会导致这个版本以及后续版本的 migration 无法执行。

需要保证数据库schema_version表中有多少行数据,程序中就应该有多少个对应版本的sql文件。也就是说脚本内容不是在原文件中做修改,而是新建一个sql文件做修改,并命名一个新的版本号。

如果修改已经导入成功的脚本文件,会因为checksum校验导致报错,因此要修改原脚本文件,要么删除flyway_schema_history表,要么新加一份文件,并且版本号增加。

Undo Migration

Versioned migration 中,还有一种特殊的类型 undo migration,可为对应版本的常规 versioned migration 进行回退操作,命名方式如下:

SpringBoot引入Flyway,及Flyway简单了解_第2张图片

Undo Migration

此功能为收费功能,在社区版 Flyway 中无法使用。

Repeatable Migration

Repeatable migration 包括描述和校验值,没有版本号信息,会在每次校验值(migration 内容变化会导致校验值变化)发生变化时重复执行,命名方式如下:

SpringBoot引入Flyway,及Flyway简单了解_第3张图片

Repeatable Migration

Repeatable migration 会在所有的 versioned migration 都执行过后再进行执行,Repeatable migration 内部按照其文件名中描述(description)部分的顺序执行。

在 repeatable migration 中需保证其中内容可重复执行,比如在 DDL 中使用 CREATE OR REPLACE

Baseline

当数据中已经存在内容时,再引入 Flyway,可通过 Baseline 设定一条基线。

SpringBoot引入Flyway,及Flyway简单了解_第4张图片

Baselineg

如果想将基线之前的数据库中表结构和数据纳入 Flyway 一同管理,可以将基线前的状态导出成数据库脚本,通过 versioned migration 添加至 flyway 中,并设定 baselin version,Flyway 会忽略基线版本号(包括)之前版本的所有 migration。

如果不想管理基线之前的数据库状态(比如多模块或应用操作同一数据库,互相之间不受影响),可以只告诉 Flyway 执行 migration 的时候是存在基线的,这样就不会报出数据库非空的异常。

其他问题

执行方式

Flyway 的 migration 会在 Spring Boot 应用启动时自动执行,如果不想通过启动应用的方式执行,官方提供了命令行、API、以及 Maven 和 Gradle 插件的方式,但总的来说都会麻烦一些,因为需要将已经在 Spring Boot 中配置的参数,再到其他执行方式所各自要求的位置重新配置一遍,实用性一般。

生产环境数据安全性

Flyway 的 Clean 命令,会将 Flyway 所连接的数据库中的所有内容全部清理掉,不论其中的表或数据是否是通过 Flyway 添加进去的。

在生产环境中使用 Flyway 确实也存在一定的风险,但这个风险不是 Flyway 本身造成的,有权连接生产库的人的任何一个误操作,都会导致生产环境数据的丢失,建议不要进行此操作。

Flyway 对此也提供了一定的防范措施,可通过禁用 Clean 命令来防止此问题发生,比如通过 Spring Boot 的 spring.flyway.clean-disabled=true 参数。

每种执行 Flyway 命令的方式均可设置此参数,建议在所有环境都禁用 Clean 命令。

SQL 报错

通过 Spring Boot 自动执行 migration 时要注意,一旦 migration 执行失败,应用启动会终止。出现 migration 执行失败时,需要将 Schema History Table 表中的失败记录处理掉,才能再次执行 migration,否则应用会一直无法启动。

out-of-order

多人开发时,可能会出现 A 写了 V1 脚本,B 写了 V2 脚本,B 的代码先合并进去了,V2 脚本先执行了,此时 A 的 V1 脚本受版本号只能增加的要求不能再执行。

这种情况可以通过将 spring.flyway.out-of-order 设置为 true 来暂时取消这个限制,不过还是强烈建议 A 将 V1 脚本版本号改为 V3。

在SpringBoot项目中引入 Flyway

在 Spring Boot 项目中,引入 Flyway 非常简单,因为在 Spring Boot 的 spring-boot-autoconfigure 中包含了 Flyway 的自动配置,只要添加 flyway 的依赖即可。

Maven 可加入:

<dependency>
    <groupId>org.flywaydbgroupId>
    <artifactId>flyway-coreartifactId>
dependency>

版本号推荐使用 Spring Boot 依赖管理中定义好的版本(即无需额外指定)。

添加 Flyway 依赖后,无需其他配置,Flyway 的功能是自动启用的,如果想停用 Flyway,需设置 spring.flyway.enabled=false

添加 sql 脚本

引入 Flyway 之后,再启动应用时,会在默认路径 classpath:db/migration 查找 sql 脚本,如果没找到会报错,影响应用启动。

可在 src/main/resources/db/migration 路径下创建 sql 文件,如 src/main/resources/db/migration/V20210930__test.sql,使应用可正常启动。

启动成功后,可在所指定的数据库中的 flyway_schema_history 表中查看初始化脚本执行状态。

可通过 spring.flyway.table=another_table 修改默认表名。

修改默认表名,可实现多个模块分别通过 Flyway 进行数据库版本控制,并连接到相同数据库的效果。

非空数据库处理

当在一个已有项目中引入 Flyway 时,数据库中可能已经存在了一些表和初始化数据,此时按照上述方式引入 Flyway 时会提示如下异常:

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.FlywayException: Found non-empty schema(s) `demo` but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.

此时需要设定 spring.flyway.baseline-on-migrate=true 参数,告诉 Flyway 在执行 sql 脚本之前,数据库是非空状态。

如果想指定 baseline version,可通过设定 spring.flyway.baseline-version=20210930 参数,以忽略 20210930 版本以及之前的所有 migration。

你可能感兴趣的:(java,数据库)