flyway

一、简单介绍

Flyway 是一款开源的数据库版本管理工具。它可以很方便的在命令行中使用,或者在Java应用程序中引入,用于管理我们的数据库版本。

在项目或产品中,很难一开始就把业务理清楚,把数据库表设计好,因此数据表也会在迭代周期不断迭代。在Java应用程序中使用Flyway,能快速有效地用于迭代数据库表结构,并保证部署到测试环境或生产环境时,数据表都是保持一致的。

在这里插入图片描述

二、为什么要使用Flyway

在多人开发的项目中,我们都习惯了使用SVN或者Git来对代码做版本控制,主要的目的就是为了解决多人开发代码冲突和版本回退的问题。

其实,数据库的变更也需要版本控制,在日常开发中,我们经常会遇到下面的问题:

  • 自己写的SQL忘了在所有环境执行。
  • 别人写的SQL我们不能确定是否都在所有环境执行过了。
  • 有人修改了已经执行过的SQL,期望再次执行。
  • 需要新增环境做数据迁移。
  • 每次发版需要手动控制先发DB版本,再发布应用版本。
  • 其它场景。

有了flyway,这些问题都能得到很好的解决。

三、flyway是如何工作的

flyway工作流程如下:

项目启动,应用程序完成数据库连接池的建立后,Flyway自动运行。
初次使用时,flyway会创建一个 flyway_schema_history 表,用于记录sql执行记录。
Flyway会扫描项目指定路径下(默认是 classpath:db/migration )的所有sql脚本,与 flyway_schema_history 表脚本记录进行比对。如果数据库记录执行过的脚本记录,与项目中的sql脚本不一致,Flyway会报错并停止项目执行。
如果校验通过,则根据表中的sql记录最大版本号,忽略所有版本号不大于该版本的脚本。再按照版本号从小到大,逐个执行其余脚本。并非真正忽略,而是会校验checksum值是否一致,以此来保证历史版本文件未被篡改。

 
最简单的理解方式是:简单我们在一个空数据库上部署集成了Flyway的应用:
请添加图片描述
Flyway将在这个空数据中创建一张表,用于记录migration的执行情况,表名称默认为:flyway_schema_history,老版本的表名称:schema_version

请添加图片描述
紧接着,Flyway根据表中的记录决定是否执行应用程序包中提供的migration

请添加图片描述

最后将执行结果写入flyway_schema_histor并校验执行结果

在这里插入图片描述

下次版本迭代时,提供新的migration,会根据flyway_schema_histor的记录执行新migration

请添加图片描述

请添加图片描述
在这里插入图片描述

四、测试V

引入依赖

  • springboot主依赖版本:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
  • 数据库连接、flyway依赖:
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
            <version>5.2.4</version>
        </dependency>

    </dependencies>

【额外注意:】必须增加数据库连接pom依赖!

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

否则会出现项目启动成功,但不会自动生成表的问题

配置数据库连接

server:
  port: 80
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/flyway?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql8的驱动,注意时区,如果是使用 MySQL 8 之前的驱动,可以是 com.mysql.jdbc.Driver

  flyway:
    locations: classpath:db/migration # 默认配置
    enabled: true # 默认
    baseline-on-migrate: true
    clean-on-validation-error: false

启动类

package com.xxxx.lln;

import org.springframework.boot.SpringApplication;

/**
 * 启动类
 *
 * @author : li.linnan
 * @create : 2023/2/27
 */
@org.springframework.boot.autoconfigure.SpringBootApplication
public class SpringBootApplication {
    public static void main(String[] args) {
        try {
            SpringApplication.run(SpringBootApplication.class,args);
        }catch (Exception e){
            System.out.println(e);
        }
    }
}

添加脚本

首先需要在classpath目录下,创建一个名为db/migration的文件夹。

然后向该文件夹内,增加SQL脚本。编写SQL脚本需要注意以下几点:

1、仅需要执行一次的脚本,以V开头,后面跟上0~9的数字组合,数字之间可以使用.或者_进行分割。然后再以两个下划线 __进行分割,其后跟上文件名称,最后以.sql结尾。

如: V1__create_user_ddl.sql、V2__create_user.sql。

2、需要重复执行的SQL,则需要以R开头。后面再以两个下划线分割,其后跟文件名称,最后以.sql结尾。

如:R__truncate_user_dml.sql

编写如下所示的测试脚本V1.0.0__Create_user_manage.sql信息,如下所示:

CREATE TABLE IF NOT EXISTS `USER`(
    `USER_ID`          INT(11)           NOT NULL AUTO_INCREMENT,
    `USER_NAME`        VARCHAR(100)      NOT NULL COMMENT '用户姓名',
    `AGE`              INT(3)            NOT NULL COMMENT '年龄',
    `CREATED_TIME`     datetime          NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `CREATED_BY`       varchar(100)      NOT NULL DEFAULT 'UNKNOWN',
    `UPDATED_TIME`     datetime          NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `UPDATED_BY`       varchar(100)      NOT NULL DEFAULT 'UNKNOWN',
    PRIMARY KEY (`USER_ID`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

项目结构概览

在这里插入图片描述

项目启动,观察日志和数据库结果

在这里插入图片描述

在这里插入图片描述

为什么会出现两张表?

flyway_schema_history是一个flyway管理各个版本关系的表,主要用于维护和管理开发者本地的脚本版本信息。

在这里插入图片描述

另一张表,则是刚刚的SQL脚本执行结果表,如下所示:
在这里插入图片描述

验证V只能执行一次

向数据表里再加一个字段

CREATE TABLE IF NOT EXISTS `USER`(
    `USER_ID`          INT(11)           NOT NULL AUTO_INCREMENT,
    `USER_NAME`        VARCHAR(100)      NOT NULL COMMENT '用户姓名',
    `AGE`              INT(3)            NOT NULL COMMENT '年龄',
    `CREATED_TIME`     datetime          NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `CREATED_BY`       varchar(100)      NOT NULL DEFAULT 'UNKNOWN',
    `UPDATED_TIME`     datetime          NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `UPDATED_BY`       varchar(100)      NOT NULL DEFAULT 'UNKNOWN',
    PRIMARY KEY (`USER_ID`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `user` add column USER_POSITION varchar(11) default null comment '位置';

重启项目,观察现象:
在这里插入图片描述

从控制台日志信息可以看出:

V开头的脚本文件,在项目启动时,会去flyway_schema_history表中匹配判断!
如果文本信息不匹配,则直接报错!!!!

强制修改初始化脚本

1.把数据库和脚本都同步修改掉
2.用最新的checksum,即用上图中的1642862594替换掉数据表flyway_schema_history中的checksum

基准版本

这个暂时没搞明白

如果有多个版本的文件 例如:1.0.0 ;1.0.1;1.0.2
flyway 会根据版本号顺序依次执行

可能在第一次使用的时候,不想再重新执行一遍之前的sql,就需要调整 flyway自动执行的基准 版本 请修改配置 baseline-version

不想再重新执行一遍之前的sql,就需要调整 flyway自动执行的基准版本

版本号>基准版本号/当前版本号 才会执行

五、测试R

在classpath文件夹中,新增一个R__add_user_info.sql的脚本信息,其中SQL脚本如下所示:

insert into `user`(user_name,age) values('lln',35);

重启项目,观察结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

【注意】这里的 R 重复执行脚本,并不是说是启动项目后不断执行!
而是,每次启动项目,都会重新校验对应的 R__add_user_info.sql 内容是否变更,如果变更则重新执行。

修改R__add_user_info.sql中的信息,重新启动项目:

-- insert into `user`(user_name,age) values('lln',35);

insert into `user`(user_name,age) values('xiangjiao',22);

在这里插入图片描述
在这里插入图片描述

变更数据库字段

正常开发中,字段信息的变更,往往不是很常见,这个要看需求。

如果因为需求的出现,导致需要在数据库表中增加或修改字段信息,此时flyway能轻松胜任。

之前的SQL脚本中,只设定有用户名、性别等信息,但如果想增加一个密码字段,此时则需要新增一个脚本。

V1.0.3__add_user_pwd.sql,其中脚本内容如下所示:

ALTER TABLE `user` add column user_pwd varchar(11) default null comment '密码' after `age`;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Flyway历史记录表

Flyway通过创建flyway_history_schema来记录迁移,表中的主要字段如下:

字段名描述
installed_rank执行排名,值越低优先级越高,即版本越低越先执行
version执行的版本
description版本描述
type脚本类型
script脚本文件名
checksum校验和,用于检测是由有更改
installed_by脚本执行人员
installed_on执行时间
execution_time执行脚本所耗时间
success是否执行成功(0-失败,1成功)

Flyway配置清单

flyway.baseline-description对执行迁移时基准版本的描述.
flyway.baseline-on-migrate当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false.
flyway.baseline-version开始执行基准迁移时对现有的schema的版本打标签,默认值为1.
flyway.check-location检查迁移脚本的位置是否存在,默认false.
flyway.clean-on-validation-error当发现校验错误时是否自动调用clean,默认false.
flyway.enabled是否开启flywary,默认true.
flyway.encoding设置迁移时的编码,默认UTF-8.
flyway.ignore-failed-future-migration当读取元数据表时是否忽略错误的迁移,默认false.
flyway.init-sqls当初始化好连接时要执行的SQL.
flyway.locations迁移脚本的位置,默认db/migration.
flyway.out-of-order是否允许无序的迁移,默认false.
flyway.password目标数据库的密码.
flyway.placeholder-prefix设置每个placeholder的前缀,默认${.
flyway.placeholder-replacementplaceholders是否要被替换,默认true.
flyway.placeholder-suffix设置每个placeholder的后缀,默认}.
flyway.placeholders.[placeholder name]设置placeholder的value
flyway.schemas设定需要flywary迁移的schema,大小写敏感,默认为连接默认的schema.
flyway.sql-migration-prefix迁移文件的前缀,默认为V.
flyway.sql-migration-separator迁移脚本的文件名分隔符,默认__
flyway.sql-migration-suffix迁移脚本的后缀,默认为.sql
flyway.tableflyway使用的元数据表名,默认为schema_version
flyway.target迁移时使用的目标版本,默认为latest version
flyway.url迁移时使用的JDBC URL,如果没有指定的话,将使用配置的主数据源
flyway.user迁移数据库的用户名
flyway.validate-on-migrate迁移时是否校验,默认为true
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值