logo

一、 Flyway介绍

Flyway的定位:数据库的版本控制。

Flyway是一款开源的数据库版本管理工具,Flyway可以独立于应用实现管理并跟踪数据库的变更(DDL和DML语句),Flyway根据自己的约定,不需要复杂的配置就可以实现数据的Migrate(迁移)。Migrations可以写成SQL脚本,也可以写在Java代码中,Flyway还支持Spring Boot。

使用Flyway帮助用户完成数据库迁移的工作,Flyway可以从任意一个数据库版本自动迁移到最新版本,由于迁移脚本和代码同步提交,从而保证代码和数据库时刻匹配。

二、为什么要用Flyway

随着项目的不断迭代,数据库表结构、数据都在发生着变化。甚至有的业务在多环境版本并行运行。数据为王的时代,管理好数据库的版本也成为了迫切的需要。如何能做到像 Git 之类的版本控制工具来管理数据库?Java 项目中常用 Flyway 和 Liquibase 来管理数据库版本。其中 Flyway 相对来说比较受欢迎。

在真实的项目开发中,我们每个人都会有一个应用软件和与其相对应的数据库。对于个人开发来说,这样就够了。但是,项目开发一般都不止一个人,因此一定会出现我的本地有一套软件和相应的数据库系统,另一个同事会在他的本地有一套他自己的软件和相应的数据库系统。我们需要面临的第一个问题就是我们两个人如何集成我们的数据库系统,之后还要处理如何将数据库系统迁移到测试环境和生产环境当中去。其实道理和Git合并代码一样的道理,当2个人或多个同时修改了一份代码那么我们如何进行数据库同步?在比如我们如果修改了脚本那么如何同步测试环境和生产环境,以上那么变得非常麻烦,现在就用到了我们的flyway。

三、 Flyway的工作模式

介绍Flyway是如何工作的,也可以理解为Flyway的数据库升级方案。

Flyway可以对数据库进行升级,从任意一个版本升级到最新的版本。但是升级的依据是用户自己编写的sql脚本,用户自己决定每一个版本的升级内容。

Flyway不限定脚本里面的内容,但是对脚本文件的名称有一定的命名规范要求:

image

版本号可以使用小版本,如V1.1。

具体要求:

版本号和版本描述之间,使用两个下划线分隔。

版本描述之间,使用一个下划线分隔单词。

版本号唯一:不允许多个脚本文件有相同的版本号。

使用Flyway升级,会自动创建一张历史记录表:flyway_schema_history。

这张表记录了每一次升级的记录,包括已经执行了哪些脚本,脚本的文件名,内容校验和,执行的时间和结果:

meta表数据截图

Flyway在升级数据库的时候,会检查已经执行过的版本对应的脚本是否发生变化,包括脚本文件名,以及脚本内容。如果flyway检测到发生了变化,则抛出错误,并终止升级。

如果已经执行过的脚本没有发生变化,Flyway会跳过这些脚本,依次执行后续版本的脚本,并在记录表中插入对应的升级记录。

所以,Flyway总是幂等的,而且可以支持跨版本的升级。

如果你好奇,Flyway如何检查脚本文件的内容是否有修改。你可以注意以下记录表中有一个字段checksum,它记录了脚本文件的校验和。flyway通过比对文件的校验和来检测文件的内容是否变更。

使用上面的方式,升级一个空的数据库,或者在一直使用Flyway升级方案的数据库上进行升级,都不会又问题。但是,如果在已有的数据库引入Flyway,就需要一些额外的工作。

Flyway检测数据库中是否有历史记录表,没有则代表是第一次升级。此时,flyway要求数据库是空的,并拒绝对数据库进行升级。

你可以设置baseline-on-migrate参数为true,flyway会自动将当前的数据库记录为V1版本,然后执行升级脚本。这也表示用户所准备的脚本中,V1版本的脚本会被跳过,只有V1之后的版本才会被执行。

四、Flyway 的“潜”规则

4.1 SQL文件执行顺序

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

1.0.1.1比 1.0.1版本高。

1.0.10 比1.0.9.4版本高。

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

4.2 SQL文件种类

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.3 执行流程说明

在定义脚本的时候,除了 V 字开头的脚本之外,还有一种 R 字开头的脚本,V 字开头的脚本只会执行一次,而 R 字开头的脚本,只要脚本内容发生了变化,启动时候就会执行。

使用了 Flyway 之后,如果再进行数据库版本升级,就不用修改以前的数据库脚本了,直接创建新的数据库脚本,项目在启动时检测了有新的更高版本的脚本,就会自动执行,这样,在和其他同事配合工作时,也会方便很多。因为正常我们都是从 Git 上拉代码下来,不拉数据库脚本,这样要是有人更新了数据库,其他同事不一定能够收到最新的通知,使用了 Flyway 就可以有效避免这个问题了。

4.3.1 重新执行脚本

所有的脚本,一旦执行了,就会在 flyway_schema_history 表中有记录,如果你不小心搞错了,可以手动从 flyway_schema_history 表中删除记录,然后修改 SQL 脚本后再重新启动(生产环境不建议)。

五、Spring Boot 集成 Flyway

Spring Boot 集成 Flyway

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

5.1 新 Spring Boot 项目

Dependencies页就有 Flyway 的选项,可以搜索flyway然后回车就会自动添加该依赖,或者点击SQL-->Flyway Migration勾选该项,如下图:

加入Flyway依赖

项目创建成功后,resources目录下也会多出来一个db/migration目录,这个目录用来存放数据库脚本,如下:

db/migration目录

5.2 依赖:

核心依赖:

org.flywaydb

flyway-core

完整pom:

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.erbadagang.db.flyway

flyway

0.0.1-SNAPSHOT

flyway

Flayway project for Spring Boot

1.8

UTF-8

UTF-8

2.3.0.RELEASE

org.springframework.boot

spring-boot-starter

org.flywaydb

flyway-core

org.springframework.boot

spring-boot-starter-jdbc

mysql

mysql-connector-java

5.1.48

org.springframework.boot

spring-boot-starter-test

test

org.junit.vintage

junit-vintage-engine

org.springframework.boot

spring-boot-dependencies

${spring-boot.version}

pom

import

org.apache.maven.plugins

maven-compiler-plugin

1.8

1.8

UTF-8

org.springframework.boot

spring-boot-maven-plugin

5.3 application.yml

配置数据库连接池

#############flyway##########

#服务端口

server:

port: 8080

spring:

application:

#服务名

name: flyway

main:

allow-bean-definition-overriding: true

datasource:

url: jdbc:mysql://localhost:3306/fescar?useSSL=false&useUnicode=true&characterEncoding=UTF-8

driver-class-name: com.mysql.jdbc.Driver

type: com.zaxxer.hikari.HikariDataSource # 使用 Hikari 数据库连接池

# driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: 123456

Flyway部分的配置为:

# flyway 配置

spring:

flyway:

# 启用或禁用 flyway

enabled: true

# flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。

clean-disabled: true

# SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration

locations: classpath:db/migration

# metadata 版本控制信息表 默认 flyway_schema_history

table: flyway_schema_history

# 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令

# 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。

baseline-on-migrate: true

# 指定 baseline 的版本号,默认值为 1, 低于该版本号的 SQL 文件, migrate 时会被忽略

baseline-version: 1

# 字符编码 默认 UTF-8

encoding: UTF-8

# 是否允许不按顺序迁移 开发建议 true 生产建议 false

out-of-order: false

# 需要 flyway 管控的 schema list,这里我们配置为flyway 缺省的话, 使用spring.datasource.url 配置的那个 schema,

# 可以指定多个schema, 但仅会在第一个schema下建立 metadata 表, 也仅在第一个schema应用migration sql 脚本.

# 但flyway Clean 命令会依次在这些schema下都执行一遍. 所以 确保生产 spring.flyway.clean-disabled 为 true

schemas: flyway

# 执行迁移时是否自动调用验证 当你的 版本不符合逻辑 比如 你先执行了 DML 而没有 对应的DDL 会抛出异常

validate-on-migrate: true

5.4 编写 SQL 初始化脚本

如果db/migration目录下没有SQL文件,启动项目会报错:

Flyway failed to initialize: none of the following migration scripts locations could be found:

- classpath:db/migration”

BTW:这个英文提示我断句好几次才勉强看懂,如果说成nothing in the following location是不是更容易理解?

我们先编写一个初始化 SQL 文件,向数据库添加一张sys_user表。请注意命名规则,脚本名称为V1.0.0__Add_table_user.sql 。SQL 脚本的位置在配置的 spring.flyway.locations值,即db/migration目录 下。内容为:

use `fescar`;

CREATE TABLE `sys_user`

(

`user_id` bigint NOT NULL AUTO_INCREMENT,

`username` varchar(50) NOT NULL unique ,

`encode_password` varchar(50) NOT NULL,

`age` int(3) NOT NULL,

PRIMARY KEY (`user_id`)

) ENGINE = InnoDB

DEFAULT CHARSET = utf8mb4;

insert into fescar.sys_user values (1,'guoxiuzhi','{noop}123456',18);

5.5 启动 Spring Boot 应用

可以看到如下日志信息,代表成功执行了sql。如果有问题会报相应的异常信息。

2020-07-04 15:17:29.807 INFO 12200 --- [main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.012s)

2020-07-04 15:17:29.819 INFO 12200 --- [main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway` to version 1.0.0

2020-07-04 15:17:29.896 INFO 12200 --- [main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `flyway` (execution time 00:00.086s)

Flyway 需要在 DB 中先创建一个 metadata 表 (缺省表名为 flyway_schema_history), 在该表中保存着每次 migration (迁移)的记录, 记录包含 migration 脚本的版本号和 SQL 脚本的 checksum 值。下图表示了多个版本数据库变更。

flyway_schema_history表功能

对应的 metadata 表记录:

installed_rank

version

description

type

script

checksum

installed_by

installed_on

execution_time

success

1

1.0.0

Add table user

SQL

V1.0.0__Add_table_user.sql

1963311468

root

2020-07-04 15:07:32

53

1

上面的表格由于太宽,在移动端显示被适应屏幕宽度而难于阅读,可以看下面截图数据:

meta表数据截图

Flyway 扫描文件系统或应用程序的类路径读取 DDL 和 DML 以进行迁移。根据metadata 表进行检查迁移。如果脚本声明的版本号小于或等于标记为当前版本的版本号之一,将忽略它们。其余迁移是待处理迁移:可用,但未应用。最后按版本号对它们进行排序并按顺序执行 并将执行结果写入 metadata 表。

迁移变化示意图

5.6 修改V1.0.0__Add_table_user.sql

修改sql脚本,一般int类型后面不加长度定义,将age int(3) NOT NULL ,改成age int NOT NULL 。再次启动 Spring Boot 应用 。

提示如下异常:

Caused by: org.flywaydb.core.api.FlywayException: Validate failed:

Migration checksum mismatch for migration version 1.0.0

-> Applied to database : 1963311468

-> Resolved locally : 1207766644

Flyway在升级数据库的时候,会检查已经执行过的版本对应的脚本是否发生变化,包括脚本文件名,以及脚本内容。如果flyway检测到发生了变化,则抛出错误,并终止升级。

上面抛出异常正因为我们开启了校验,所以对于checksum不一致的会抛出异常。

5.6 新建高版本SQL文件

我们新增一个版本号更高的V1.0.1__alter_table_user.sqlSQL文件。增加删除表命令和修改age int(3) NOT NULL 为age int NOT NULL 。

更高版本号的SQL文件

再次启动应用。

控制台打印成功迁移信息Migrating schema flyway to version 1.0.1:

2020-07-04 15:42:08.039 INFO 9084 --- [main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.014s)

2020-07-04 15:42:08.044 INFO 9084 --- [main] o.f.core.internal.command.DbMigrate : Current version of schema `flyway`: 1.0.0

2020-07-04 15:42:08.051 INFO 9084 --- [main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway` to version 1.0.1- alter table user

2020-07-04 15:42:08.070 INFO 9084 --- [main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `flyway` (execution time 00:00.028s)

数据库迁移记录,即flyway_schema_history表的数据如下:

六、总结

通过2个版本的SQL演示,如果有高版本的SQL文件存在于db/migration目录,当启动应用的时候就会自动执行SQL到数据库中,也就是我们的目标:使用 Flyway 进行数据库版本控制。

这里总结了一些在实际开发中的使用经验:

生产务必禁 spring.flyway.cleanDisabled=false 。

尽量避免使用 Undo 模式,使用Versioned模式新建高版本SQL文件。

开发版本号尽量根据团队来进行多层次的命名避免混乱。比如 V1.0.1__ProjectName_{Feature|Bugfix}_Developer_Description.sql ,这种命名同时也可以获取更多脚本的相关功能、开发者的信息。

spring.flyway.outOfOrder 取值 生产上使用 false,开发中使用 true。

多个系统公用一个 数据库 schema 时配置spring.flyway.table ,为不同的系统设置不同的 metadata 表名,而不使用缺省值 flyway_schema_history 。

写在最后:

本文源代码使用 Apache License 2.0开源许可协议,可从Gitee代码地址通过git clone命令下载到本地或者通过浏览器方式查看源代码。

flyway版本号_Flyway 管理数据库版本变更相关推荐

  1. 为热门项目 若依(ruoyi) 添加flyway,自动管理数据库版本

    flyway大家应该都听说过甚至用过,是一种数据库管理工具.多个人协作开发,或者是项目部署的时候,非常方便,不需要再mysql里面去初始化表结构和数据,项目启动时,根据flyway_schema_hi ...

  2. Spring Boot 2.x基础教程:使用Flyway管理数据库版本

    之前已经介绍了很多在Spring Boot中使用MySQL的案例,包含了Spring Boot最原始的 JdbcTemplate(https://blog.didispace.com/spring-b ...

  3. Maven学习总结(33)——开发人员如何使用 Flyway 插件管理数据库版本

    一.前言. 想到要管理数据库的版本,是在实际产品中遇到问题后想到的一种解决方案,当时各个环境的数据库乱作一团,没有任何一个人(开发.测试.维护人员)能够讲清楚当前环境下的数据库是哪个版本,与哪个版本的 ...

  4. flyway常用配置_Spring Boot 2.x基础教程:使用Flyway管理数据库版本

    之前已经介绍了很多在Spring Boot中使用MySQL的案例,包含了Spring Boot最原始的JdbcTemplate.Spring Data JPA以及我们国内最常用的MyBatis.同时, ...

  5. flyway版本号_Flyway版本化管理数据库脚本

    假如我们有一个叫shiny的项目,它是由一个程序Shiny-Server 和一个数据库 Shiny-DB组成的; 简单结构图如下: image.png 但是很多时候,现实开发团队是这样的: image ...

  6. SpringBoot系列: 使用 flyway 管理数据库版本

    Flyway 和 Liquibase 都是 Java 项目中常用的 DB migration 工具, 从使用简便性看,Flyway 比 Liquibase 更简单, 从 github 的 star 数 ...

  7. Spring Boot中使用Flyway来管理数据库版本

    久违了的Spring Boot系列,今天抽空更新一篇.之前写过很多篇关于数据访问的文章了,比如下面这些: 使用JdbcTemplate 使用Spring-data-jpa简化数据访问层(推荐) 多数据 ...

  8. Spring Boot教程(四十)使用Flyway来管理数据库版本

    在上面的使用JdbcTemplate一文中,主要通过spring提供的JdbcTemplate实现对用户表的增删改查操作.在实现这个例子的时候,我们事先在MySQL中创建了用户表.创建表的过程我们在实 ...

  9. flyway常用配置_Spring Boot 2 实战:使用 Flyway 管理你数据库的版本变更

    1. 前言 随着项目的不断迭代,数据库表结构.数据都在发生着变化.甚至有的业务在多环境版本并行运行.数据为王的时代,管理好数据库的版本也成为了迫切的需要.如何能做到像 Git 之类的版本控制工具来管理 ...

最新文章

  1. 添加议题模块html,WordPress 技巧:为评论模块增加更多 HTML 标签支持
  2. 打不开添加删除程序的故障
  3. document 文挡对象 - JavaScript脚本语言描述
  4. StackOverflow问题:How to share CMSComponentData between several components in Spartacus manner
  5. Visual C++中MFC消息的分类
  6. linux输入qsub显示错误,linux – 使用qsub运行shellscript的’意外的文件结束’和’错误导入功能定义’错误...
  7. python excel 数据匹配实现vlookup功能_如何用python实现excel中的vlookup功能?
  8. 嵌入式-C语言常见面试/笔试题
  9. drop table 、delete table和truncate table的区别
  10. 聊聊Spring家族中的那几百个注解
  11. L1-067 洛希极限 (10 分)
  12. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第4节 方法引用_6_方法引用_类的构造器(构造方法)引用...
  13. SHELL中变量字串中包含$时怎么办?
  14. 请用c语言写出冒泡排序的程序,请问一下这个C语言冒泡排序程序思想
  15. Delphi外挂制作
  16. h5下划线怎么设置_怎么给文本添加下划线?
  17. LaTeX安装CJK-- 添加中文支持
  18. [Maven]intellij 如何使用mvn clean
  19. 高德运维基于阿里云的最佳实践
  20. 收益用计算机怎么计算,有利网收益计算器怎么用

热门文章

  1. Spring入门程序的编写(实验一+第一章知识总结)
  2. html连接手机与电视,手机如何连接电视
  3. pycharm 教程(一)安装和首次使用
  4. 物联网设备加密的意义
  5. mysql 删除字段_MySQL命令行删除表中的一个字段
  6. T3升级U8报错相关问题解决方案:
  7. 计算机基础知识课件北京大板,计算机基础知识
  8. B样条学习NURB B样条的基函数
  9. Games101 作业2(解决黑线问题)
  10. 队列的入队、出队基本操作