Flyway
Flyway 是一款开源的数据库版本管理工具,用于管理和自动化数据库结构的变更。它可以跟踪和管理数据库的版本控制,并在应用程序启动时自动执行升级或回滚操作。
使用Flyway,你可以将数据库的变更以可重复且可控的方式应用到不同环境中,如开发、测试和生产环境。它支持多种数据库系统,包括MySQL、Oracle、PostgreSQL、SQL Server等。
Flyway将数据库结构的变更定义为一系列迁移脚本,通常是SQL脚本文件。每个迁移脚本都有一个唯一的版本号,Flyway会按照版本号的顺序依次执行这些脚本,以达到数据库结构的变更和更新。当应用程序启动时,Flyway会自动检测并执行未应用的迁移脚本,将数据库升级到最新版本。如果需要回滚到之前的版本,Flyway也提供了回滚操作的支持。
通过使用Flyway,开发团队可以更好地管理数据库结构的变更,保持不同环境之间的数据库一致性,并轻松地进行版本控制和追踪。
官方文档:https://documentation.red-gate.com/fd/
Flyway 工作流程
1、检测数据库状态:Flyway会连接到配置的数据库,并检测当前数据库的状态,包括已应用的迁移脚本版本和未应用的迁移脚本。
2、执行迁移脚本:Flyway会将未应用的迁移脚本按照版本号的顺序逐一执行。它会查找项目中指定的迁移脚本目录(默认为db/migration),并依次运行其中的SQL脚本。
3、更新数据库状态:每当一个迁移脚本成功执行后,Flyway会将其记录为已应用的脚本,并将其版本号存储在数据库的元数据表( flyway_schema_history)中,以便下次启动时进行跟踪和管理。
Spring Boot集成Flyway
1、添加依赖
在项目的pom.xml文件中,添加Flyway的Maven依赖,如果是springboot 2.xx,使用5.2.1或5.2.4:
java
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>${flyway-core.version}</version>
</dependency>
2、数据库连接信息配置
在Spring Boot项目的application.properties或者application.yml文件中配置数据库的连接信息,例如:
java
spring.datasource.url=jdbc:mysql://localhost:3306/db_example
spring.datasource.username=dbuser
spring.datasource.password=dbpass
3、Flyway配置
在Spring Boot项目的application.properties或者application.yml文件中进行Flyway的相关配置,例如
java
# Flyway配置
#开启flyway功能,默认为true
spring.flyway.enabled=true
# 用于存储迁移历史记录的表名,默认为flyway_schema_history
spring.flyway.table=flyway_schema_history
# 迁移脚本编码,默认为UTF-8
spring.flyway.encoding=UTF-8
# 当迁移数据库存在但没有元数据的表时,自动执行基准迁移,新建flyway_schema_history表
spring.flyway.baseline-on-migrate=true
# 数据库迁移脚本的位置,默认为classpath:db/migration
spring.flyway.locations=classpath:db/migration
# SQL迁移脚本文件名前缀,默认为V
spring.flyway.sql-migration-prefix=V
# SQL迁移脚本文件名后缀,默认为.sql
spring.flyway.sql-migration-suffixes=.sql
# 是否在迁移时验证脚本,默认为true
spring.flyway.validate-on-migrate=true
# 检测迁移脚本的路径是否存在,默认为true,如不存在,则抛出异常,如果不想抛出异常可设为flase
spring.flyway.check-location=false
# 用于控制是否禁用 Flyway 的 clean 操作。
spring.flyway.clean-disabled=true
大家可以按照自己的需求来进行配置,上述配置除了spring.flyway.baseline-on-migrate和spring.flyway.clean-disabled,其他都比较见名知义,所以下面讲解下
spring.flyway.baseline-on-migrate
当spring.flyway.baseline-on-migrate属性设置为true时,Flyway会自动创建一个名为flyway_schema_history的表,并将当前数据库的schema版本设置为目前最新的迁移脚本版本。
具体来说,这个属性的作用包括:
- 当数据库中不存在迁移历史记录表时,Flyway 会自动创建该表,并将当前已经存在的数据库对象标记为已迁移状态。
- 当数据库中存在迁移历史记录表,但版本号低于最新的迁移脚本版本时,Flyway 也会自动创建一个基线版本,从而将现有的数据库对象标记为已迁移状态,并开始应用最新的迁移脚本。
这样做的目的是确保在已有数据库上使用 Flyway 进行迁移时,无论数据库是否已经有迁移历史记录,都能够正确地进行迁移操作。这在初始化应用程序时特别有用,因为它允许你在部署应用程序到新环境时,自动初始化数据库并应用最新的迁移脚本。
spring.flyway.clean-disabled
spring.flyway.clean-disabled 用于控制是否禁用 Flyway 的 clean 操作。
clean 操作是 Flyway 的一个功能,可以清空数据库中的所有对象(比如表、视图、存储过程等),以便进行全新的数据库迁移。在开发和测试阶段,这可能是有用的,因为它可以确保每次都从一个干净的数据库状态开始运行。但在生产环境中,执行 clean 操作可能会导致数据丢失,因此通常需要禁用它。
4、创建迁移脚本
在项目的src/main/resources/db/migration目录下创建数据库迁移脚本,命名规范为V1__Description.sql,其中V1是版本号,Description是描述。例如,可以创建一个V1.1__CreateTable.sql的文件来创建表。
Flyway 的 SQL 脚本命名规则:
-
版本号:SQL 脚本的文件名应该以一个版本号开头,版本号可以是数字序列或者带有点号分隔的数字序列,用来表示数据库结构的变更顺序。例如,V1.1__Create_Table.sql 或 V1.2__Add_Column.sql。
-
描述性名称:在版本号之后,使用双下划线 __ 分隔,并在其后添加描述性的名称,用来清晰地表明这个脚本的作用。例如,V1__Create_Table.sql 中的 "Create_Table" 就是一个描述性的名称。
根据以上的命名规则,Flyway 会按照版本号的顺序依次执行 SQL 脚本。在 SQL 脚本的编写中,你可以包含所有标准的 SQL 语句,比如 CREATE TABLE、ALTER TABLE、INSERT 等,以及适用于特定数据库的特性和语法。
如果我们一个版本下有多个文件,那还可以在版本后面使用序号来区分排序
实例:V1.1.0版本下,001为创建脚本,002为更新脚本
java
V1.1.0_001__create_table.sql
V1.1.0_002__insert_table.sql
Flyway 还提供了一种特殊的 SQL 脚本命名规则,用于标识可重复执行的 SQL 脚本。这种命名规则是基于前缀 R__ 的方式,以大写的"R"开头,后面再以两个下划线分割,其后跟文件名称,最后以.sql结尾
命名规则如下:
java
格式:R__<描述>.sql
示例:R__Initialize_Data.sql、R__Cleanup_Data.sql
可重复执行的 SQL 脚本指的是可以在任何数据库版本上多次运行而不会造成影响的脚本,通常用于执行一些初始化或数据清理等操作。
5、启动项目,flyway执行脚本
当我们把spring.flyway.baseline-on-migrate属性设为true的时候,第一次启动项目会为我们创建flyway_schema_history表,并执行相应的脚本
下面是表的字段说明
java
installed_rank:已安装的迁移脚本的排名(从 1 开始)。
version:迁移脚本的版本号。
description:迁移脚本的描述。
type:迁移脚本的类型(SQL、JAVA 等)。
script:迁移脚本的文件名。
checksum:迁移脚本的校验和。
installed_by:安装迁移脚本的用户。
installed_on:安装迁移脚本的时间戳。
execution_time:执行迁移脚本所需的时间(以毫秒为单位)。
success:表示迁移脚本是否成功安装。
说明,如果我们是spring.flyway.baseline-on-migrate=true自动生成的flyway_schema_history表,那么version字段默认值为1,此时的sql脚本必须比1大才会执行,比如V1.1,V1.1.0,V2等,如果使用V1命名我们的sql脚本,则脚本不会执行