目录

1. 前言

2. Flyway 简介

3. Flyway 规则

4. Spring Boot 集成 Flyway

4.1 Flyway 依赖

4.2 Flyway 配置

4.3 Flyway 迁移实战

4.3.1 创建初始化脚本

4.3.2 创建变更脚本

5. Flyway最佳实践

6. 总结


1. 前言

我们都知道,Git/SVN 是代码界的版本控制工具,那么,Flyway 就是数据库界的版本控制工具,它可以记录数据库的变化记录。

可能很多公司都是通过人工去维护、同步数据库脚本,就比如我现在所在的公司。但经常会遇到疏忽而遗漏的情况,举个简单的例子:

我们在开发环境对某个表新增了一个字段,而提交测试时却忘了提交该 SQL 脚本,导致出现bug而测试中断,从而影响开发、测试工作效率。严重点的话,如果是在生产环境才发现问题,将会是重大线上事故,年终奖就别考虑了~ 

而有了 Flyway,我们可以按版本约定,统一管理所有的 SQL 脚本变更,在所有环境自动同步数据库,而无需人为手工控制,再也不用担心因数据库不同步而导致的各种环境问题了。绩效也杠杠滴 :)。

2. Flyway 简介

Flyway 是一个简单开源数据库版本控制器(约定大于配置),它支持 SQL、Java API 和命令行的运行方式,还提供一系列的插件支持(Maven、Gradle、ANT等)。

主要支持的命令:

  • Migrate(迁移)
  • Clean(清理所有配置的对象)
  • Info(显示迁移状态和细节)
  • Validate(验证迁移规则)
  • Undo(撤消最近的迁移)
  • Baseline(建立基线)
  • Repair(修复迁移历史表)

Flyway 大受欢迎是因为它具有以下优点:

  • 简单 非常容易安装和学习,同时迁移的方式也很容易被开发者接受。
  • 专一 Flyway 专注于搞数据库迁移、版本控制而并没有其它副作用。
  • 强大 专为连续交付而设计。让 Flyway 在应用程序启动时迁移数据库。

官方网站:https://flywaydb.org/

3. Flyway 规则

Flyway 是如何比较两个 SQL 文件的先后顺序的呢?它采用 左对齐原则,缺位用0代替。举几个例子:

1.0.0.1 比 1.0.0 版本高。

1.0.10 比 1.0.9.4 版本高。

1.0.0_1 比 1.0.0 版本高。

1_0_0_1 比 1_0_0 版本高。

1.0.10 和 1.0.010 版本号一样高,这是因为每个版本号部分的前导 0 会被忽略。

Flyway 将 SQL 文件分为 Versioned 、Repeatable 和 Undo 三种:

  • Versioned 用于版本升级,每个版本有唯一的版本号并只能执行一次。
  • Repeatable 可重复执行,当 Flyway 检测到 Repeatable 类型的 SQL 脚本的 checksum 有变动,Flyway 就会重新执行该脚本,它并不用于版本更新,这类的 migration 总是在 Versioned 执行之后才被执行。
  • Undo 用于撤销具有相同版本的版本化迁移带来的影响。但是该回滚过于粗暴,过于机械化,一般不推荐使用。一般建议使用 Versioned 模式来解决。

这三种的命名规则如下图:

  • Prefix 可配置,前缀标识,默认值 V 表示 Versioned, R 表示 Repeatable, U 表示 Undo。
  • Version 标识版本号, 由一个或多个数字构成,数字之间的分隔符可用点 . 或下划线 _。
  • Separator 可配置,用于分隔版本标识与描述信息,默认为两个下划线 __。
  • Description 描述信息,文字之间可以用下划线 _ 或空格 分隔。
  • Suffix 可配置,后续标识,默认为 .sql

4. Spring Boot 集成 Flyway

Spring Boot 提供了对 Flyway 的自动配置,使我们可以开箱即用 Flyway 进行数据库版本控制。

本文演示环境:

  • JDK 1.8
  • Spring Boot 2.7.18
  • MySQL 8.0

4.1 Flyway 依赖

spring-boot-dependencies 默认提供了对 Flyway 的版本管理,这里仅展示核心依赖:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-jdbc</artifactId>
	</dependency>
	<dependency>
		<groupId>com.mysql</groupId>
		<artifactId>mysql-connector-j</artifactId>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.flywaydb</groupId>
		<artifactId>flyway-core</artifactId>
	</dependency>
	<!-- MySQL 8 需要添加该依赖 -->
	<dependency>
		<groupId>org.flywaydb</groupId>
		<artifactId>flyway-mysql</artifactId>
	</dependency>
</dependencies>

4.2 Flyway 配置

Spring Boot 默认提供了对 Flyway 的自动配置:

org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration

所以,在Spring Boot 项目中,我们仅仅只要提供对应的配置参数即可:

# 数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

# 启动flyway migration, 默认为true
spring.flyway.enabled=true
# flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。
spring.flyway.clean-disabled=true
# SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration
spring.flyway.locations[0]=classpath:db/migration
#  metadata 版本控制历史表 默认 flyway_schema_history
spring.flyway.table=flyway_schema_history
# 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令
# 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。
spring.flyway.baseline-on-migrate=true

Flyway 也是遵循 约定大于配置 的思想,更多 Flyway 的参数配置可以参考这个类:

org.springframework.boot.autoconfigure.flyway.FlywayProperties

4.3 Flyway 迁移实战

4.3.1 创建初始化脚本

首先,创建三个迁移脚本,相当于项目初始化:

  • V1.0.0_1__create_user.sql
  • V1.0.0_2__create_role.sql
  • R__init_data.sql

请注意命名规则

具体 SQL 脚本内容就不贴上来了,完整的示例代码已提交 Gitee:

https://gitee.com/haitao9481/springboot-flyway-demo

1)首次启动

从启动日志可以看出,已经迁移了3个脚本,并将当前版本更新到了 V1.0.0.2:

查看数据库,Flyway 历史表和业务表及数据都已经创建:

 

2)不修改再次启动 

在不修改任何代码的情况下再次启动:

可以看到成功验证了 3 个迁移脚本,打印了当前版本号。因为当前没有比1.0.0.2更大的版本号,所以不会进行迁移。

4.3.2 创建变更脚本

我们再新增一个 SQL 脚本,相当于项目版本迭代过程中产生的 SQL 变更:

  • V1.0.1_1__alert_user.sql

对user表新增一个字段:create_time。

我们再次启动下:

成功迁移,当前版本来到了 V1.0.1.1。 

5. Flyway最佳实践

通过上面的介绍相信你很快就会使用 Flyway 进行数据库版本控制了。这里总结了一些在实际开发中的使用经验:

  1. 生产环境请务必设置 spring.flyway.clean-disabled=true
  2. 尽量避免使用 Undo 模式。
  3. 开发版本号尽量根据团队来进行多层次的命名避免混乱。比如   Vx.y.z_{sequence}__{create|alert|feature|fix}_Description_Timestamp.sql ,这种命名可以获取更多脚本相关功能的信息。
  4. 多个系统公用一个数据库 schema 时配置 spring.flyway.table 为不同的系统设置不同的 metadata 表名而不使用缺省值 flyway_schema_history

6. 总结

我们对 Flyway 数据库版本migration工具进行了介绍,并在Spring Boot应用中集成。Flyway 使用简单、自动化、开箱即用,这将大大规范我们的数据库管理,提高生产效率。

本文完整示例代码已上传 Gitee:

https://gitee.com/haitao9481/springboot-flyway-demo

如果您觉得本文不错,欢迎转发分享,原创不易,Hyatt需要您的鼓励。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐