【器篇】【Flyway】 Flyway 概述

一.引言来

在软件项目开发工程中,一般来说项目都是几个开发人员齐头并进的,常常遇到的事情是,大家都同时提交数据库表修改语句后,并不告知其它人,或者几个开发人员同时修改一个表结构,导致其他人运行项目出错。

还有在项目上线运行过程中,常常会因为管理数据库表结构或者表数据版本而发愁,甚至有的时候还不得不为生产数据做迁移操作。

以上的问题,我们一般的操作都是约定+脚本,但效率不高,并且常常会因为版本冲突,不得不手动merge。这个时候一个敏捷工具,用于数据库的移植的Flyway应用而生,它的主要用于在你的应用版本不断升级的同时,升级你的数据库结构和里面的数据。

二、介绍来

1. Flyway 的特色

Flyway 大受欢迎是由于它具备如下优势:

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

2. Flyway 的工作机制

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

【器篇】【Flyway】 Flyway 概述_第1张图片

对应的 metadata 表记录:spring

installed_rank version description type script checksum installed_by installed_on execution_time success
1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true
2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true

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

【器篇】【Flyway】 Flyway 概述_第2张图片

对应的 metadata 表记录:数据库

installed_rank version description type script checksum installed_by installed_on execution_time success
1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true
2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true
3 2.1 Refactoring JDBC V2_1__Refactoring axel 2016-02-10 17:45:05.4 251 true

Flyway 支持命令行(须要下载命令行工具)和 Java Api ,也支持构建工具 MavenGradle 。这里咱们将目光放在 Java Api 上。

3. Flyway 的规则

Flyway 是如何比较两个 SQL 文件的前后顺序呢?它采用 采用左对齐原则, 缺位用 0 代替

1.0.1.1 比 1.0.1 版本高

1.0.10 比 1.0.9.4 版本高

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

FlywaySQL 文件分为 VersionedRepeatableUndo 三种:

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

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

【器篇】【Flyway】 Flyway 概述_第3张图片

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

4.flyway命令行

flyway 提供命令行工具, 常用的命令包括:

  • Clean: 删除所有创建的数据库对象, 包括用户、表、视图等. 注意不要在生产库上执行 clean 操作.
  • Migrate: 对数据库依次应用版本更改.
  • Info: 获取目前数据库的状态. 那些迁移已经完成, 那些迁移待完成. 所有迁移的执行时间以及结果.
  • Validate: 验证已 Apply 的脚本是否有变更, Flyway 的 Migration 默认先做 Validate.
  • Baseline: 根据现有的数据库结构生成一个基准迁移脚本.
  • Repair: 修复命令尽量不要使用, 修复场景有: 1. 移除失败的 migration 记录. 2.已经应用的 SQL 脚本被修改, 我们想重新应用该 SQL 脚本.

maven 插件

           
                org.flywaydb
                flyway-maven-plugin
                
                    ${flyway.user}
                    ${flyway.password}}
                    ${flyway.url}
                
            

5.flyway 最佳实践

1.SQL 的文件名

开发环境和生产环境的 migration SQL 不共用. 开发过程往往是多人协作开发, DB migration 也相对比较频繁, 所以 SQL 脚本会很多. 而生产环境 DB migration 往往由 DBA 完成, 每次升级通常需要提交一个 SQL 脚本.

DDL DML 分开

  • 开发环境 SQL 文件建议采用时间戳作为版本号, 多人一起开发不会导致版本号争用, 同时再加上生产环境的版本号, 这样的话, 将来手工 merge 成生产环境 V1.2d migration 脚本也比较方便, SQL 文件示例:

    • V20180317.14.59__V1.2_Add_SomeTables.sql
    • V20180317.14.59__V1.0.1_ProjectName_{Feature|fix}_Developer_Description.sql
  • 生产环境 SQL 文件, 应该是手动 merge 开发环境的 SQL 脚本, 版本号按照正常的版本, 比如 V2.1.5_001__Unique_User_Names.sql
2. migration 后的SQL 脚本不应该再被修改.
3. spring.flyway.outOfOrder 取值 true /false

对于开发环境, 可能是多人协作开发, 很可能先 apply 了自己本地的最新 SQL 代码, 然后发现其他同事早先时候提交的 SQL 代码还没有 apply, 所以 开发环境应该设置 spring.flyway.outOfOrder=true, 这样 flyway 将能加载漏掉的老版本 SQL 文件; 而生产环境应该设置 spring.flyway.outOfOrder=false

4. 多个系统公用要 DB schema

很多时候多个系统公用一个 DB schema , 这时候使用 spring.flyway.table 为不同的系统设置不同的 metadata 表, 缺省为 flyway_schema_history

5.尽量配置.sql到filesystem,而不是项目工程下,原因是方便替换,并不占用jar包大小
6.不推荐使用Undo,太过粗暴

7.实际工程配置和目录

  # flyway 配置内容,对应 FlywayAutoConfiguration.FlywayConfiguration 配置项
  flyway:
    enabled: true # 开启 Flyway 功能
    cleanDisabled: true # 禁用 Flyway 所有的 drop 相关的逻辑,避免出现跑路的情况。
    locations: # 迁移脚本目录
      - classpath:db/migration/dev # 配置 SQL-based 的 SQL 脚本在该目录下
    check-location: false # 是否校验迁移脚本目录下。如果配置为 true ,代表需要校验。此时,如果目录下没有迁移脚本,会抛出 IllegalStateException 异常
    url: jdbc:mysql://192.168.8.94:3399/flyway-test?useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
    user: root # 数据库账号
    password: 1234123 #数据库密码
    baseline-version: 1.0
    baseline-description: "baseline"
    encoding: UTF-8
    out-of-order: true # 是否容许不按顺序迁移 开发建议 true  生产建议 false
    # 如果指定 schema 包含了其他表,但没有 flyway schema history 表的话, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令.
    # 设置 spring.flyway.baseline-on-migrate 为 true 后, flyway 将在需要 baseline 的时候, 自动执行一次 baseline.
    baselineOnMigrate: true
    table: flyway_schema_history

项目工程目录
【器篇】【Flyway】 Flyway 概述_第4张图片

三、扩展来

除开Flyway,还有其它的数据库迁移和版本控制工具,例如强大的Liquibase。两者具体的差异,在后续的文章阐述。在以往的经验中,小项目,整体变动不大的用Flyway,而大应用和企业应用用Liquibase更合适。

你可能感兴趣的:(flyway,mysql)