数据库脚本管理工具Flyway

写在前面

  最近由于项目变更比较大,需要经常修改表结构,然后对应的测试,开发,生产环境数据库均要修改,有时候一不小心就忘记修改某个环境下的数据库了,

等出问题才发现表结构没有更新,如果项目还没上线,还可以把表删除了重新创建,但是如果项目已经上线了,就不能这样简单粗暴了,我们需要通过 SQL 脚本

在已有数据表的基础上进行升级。鉴于这种情况,于是决定寻找数据库版本控制工具。

在Java这部分,对数据库版本控制的主要有两个工具:

  • Flyway
  • Liquibase

两个工具各有千秋,但是核心功能都是数据库的版本管理,这里主要来看 Flyway。就像我们使用 Git 来管理代码版本一样,Flyway 可以用来管理数据库版本。

Flyway官网地址:https://flywaydb.org

数据库脚本管理工具Flyway_第1张图片

1、Flyway是如何工作的

关于FlyWay工作原理,官网给出了具体的工作原理图。官网原理图地址:https://flywaydb.org/getstarted/how

这里简单记录一下,仅做备忘。

1.1 场景一:使用Flyway从无到有创建数据库

数据库脚本管理工具Flyway_第2张图片

 Flyway用'schema_version_history'数据表存放数据库schema的历史记录,跟踪数据库结构的变更;

由于刚开始数据库为空,Flyway找不到schema_version_history数据表,所以Flyway找不到它,就在数据库中创建了此表,

之后我们则需要在项目中定义Migration,通常用SQL或Java定义。

如下图所示,Flyway在运行时会顺序执行上图中的Migration1和Migration 2来实现对数据库的更新;同时'schema_version_history'表也会记录下这两次修改。

数据库脚本管理工具Flyway_第3张图片

 'schema_version_history'表记录修改历史。如下图所示:

 说明:

复制代码

脚本文件名(对应flyway_schema_history表的script字段)定义规则:
    常用格式如下:
    $PREFIX$VERSION__$REMARK.$SUBFIX
说明:
$prefix  表示 前缀,可在配置中指定,默认为 V;
$version 表示 版本号,版本号中也可以使用 . 或 _分隔,在解析时会将 _ 转换为 . 再保存到flyway_schema_history表的version字段中;
$remark  表示 备注,解析后会将这部分写入到描述字段中;
$subfix  表示 后缀,可在配置中指定,默认为 .sql ;
版本号与备注之前使用__分隔;
例如: V20200307_01__initial.sql

复制代码

1.2 场景二:基于已有数据库更新

在此场景下,Flyway仍然会遍历项目中定义的各个Migration,并参照schema_version_history数据表,忽略版本号低于或等于当前版本的Migration,

剩下的就是Pending Migration(待处理迁移版本),然后按照版本号顺序执行Pending Migration,如下图所示:

数据库脚本管理工具Flyway_第4张图片

  'schema_version_history'表记录修改历史。如下图所示:

 因此,每当我们要对数据库的DDL或者DML进行迁移时,就只需要定义一个更高版本的Migration。

2、Spring Boot整合 Flyway

这部分也可以参考官网使用指导,官网整合地址:https://flywaydb.org/documentation/plugins/springboot

数据库脚本管理工具Flyway_第5张图片

 2.1 整合步骤

2.1.1 在项目的pom文件中导入Flyway依赖,目前官网最新版本如下:


    org.flywaydb
    flyway-core
    6.3.0

 2.1.2 在application.properties或者application.yml文件添加配置

复制代码

# 说明,在spring boot 1.x中,属性前缀为flyway,在spring boot 2.x中为spring.flyway,这里需要区分不同版本
Spring.flyway:
  # 到新的环境中数据库中有数据,且没有flyway_schema_history表时,是否执行迁移操作。
    如果设置为false,在启动时会报错,并停止迁移;
    如果设置为true,则生成history表并完成所有的迁移,要根据实际情况设置;
  baseline-on-migrate: false
  # 执行时标记的tag 默认为<>
  baseline-description: <>
  # 是否启用flyway
  enabled: true
  # 检测迁移脚本的路径是否存在,如不存在,则抛出异常
  check-location: true
  # 脚本位置
  locations: classpath:db/migration
  # 在迁移时,是否校验脚本,假设V1.0__初始.sql已经迁移过了,在下次启动时会校验该脚本是否有变更过,则抛出异常
  validate-on-migrate: true
特别说明:
   如果非空数据库迁移,在目标数据库中手动建flyway_schema_history表并手动写入初始化的脚本记录,
   使flyway跳过最初的校验即可,后续可以保证版本的统一;

复制代码

2.1.3 创建迁移数据库脚本文件

可以在项目模块下的 resources 目录下,手动创建 db/migration 目录,然后在该目录下创建数据库脚本,数据库脚本的命名方式可以参考上面的说明:

“脚本文件名(对应flyway_schema_history表的script字段)定义规则”,当然也可以看下面:

 

脚本文件名(对应flyway_schema_history表的script字段)定义规则:
    常用格式如下:
    $PREFIX$VERSION__$REMARK.$SUBFIX
说明:
$prefix  表示 前缀,可在配置中指定,默认为 V;
$version 表示 版本号,版本号中也可以使用 . 或 _分隔,在解析时会将 _ 转换为 . 再保存到flyway_schema_history表的version字段中;
$remark  表示 备注,解析后会将这部分写入到描述字段中;
$subfix  表示 后缀,可在配置中指定,默认为 .sql ;
版本号与备注之前使用__分隔;
例如: V20200307_01__initial.sql

复制代码

完成这些之后,在数据库中创建一个空的目标数据库,然后启动项目进行验证。

2.1.4 验证

项目启动有如下日志信息,表明校验成功:

补充:

如果是在一个全新的项目中使用 Flyway,那么在新建一个 Spring Boot 项目时,就有 Flyway 的选项,只需要勾选即可,如下图所示:

数据库脚本管理工具Flyway_第6张图片

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

数据库脚本管理工具Flyway_第7张图片

         

                   Flyway与Liquibase对比

Spring Boot为两款流行的数据库迁移库提供了自动配置支持。
    Flyway(http://flywaydb.org)
    Liquibase(http://www.liquibase.org)

1. 用Flyway定义数据库迁移过程

    1)原理:Flyway是一个非常简单的开源数据库迁移库,使用SQL来定义迁移脚本。它的理念是,每个脚本都有一个版本号,Flyway会顺序执行这些脚本,让数据库达到期望的状态。它也会记录已执行的脚本状态,不会重复执行。Flyway脚本就是SQL。让其发挥作用的是其在Classpath里的位置和文件名。Flyway脚本都遵循一个命名规范,含有版本号。例如:V2_test.sql。所有Flyway脚本的名字都以大写字母V开头,随后是脚本的版本号。后面跟着两个下划线和对脚本的描述。Flyway脚本需要放在相对于应用程序Classpath根路径,在src/main/resources/db/migration路径下。在应用程序部署并运行起来后,Spring Boot会检测到Classpath里的Flyway,自动配置所需的Bean。Flyway会依次查看/db/migration里的脚本,如果没有执行过就运行这些脚本。每个脚本都执行过后,向schema_version表里写一条记录。应用程序下次启动时,Flyway会先看schema_version里的记录,跳过那些脚本。

    2)优点:SQL用起来便捷顺手。

    3)缺点:无法跨平台使用。

2. 用Liquibase定义数据库迁移过程

    1)原理:支持XML、YAML和JSON格式的迁移脚本。默认情况下,Bean会在/db/changelog(相对于Classpath根目录)里查找db.changelog-master.yaml文件。Liquibase变更集都集中在一个文件里。changeset命令后的那行有一个id属性,要对数据库进行后续变更。可以添加一个新的changeset,只要id不一样就行。此外,id属性也不一定是数字,可以包含任意内容。应用程序启动时,Liquibase会读取db.changelog-master.yaml里的变更集指令集,与之前写入databaseChangeLog表里的内容做对比,随后执行未运行过的变更集。

    2)优点:可以跨平台使用

    3)缺点:迁移脚本需要花费精力去维护

 

参考文档: 

https://blog.csdn.net/u013454855/article/details/104882523/

https://www.cnblogs.com/wusha/p/8601954.html

https://www.cnblogs.com/cndarren/p/12435787.html

 

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