简介

本文基于springboot2集成使用

flyway是什么

flyway是一款开源的资料库版本管理工具,它更倾向于规约优于配置的方式。
flyway可以独立于应用实现管理并跟踪资料库变更,支援资料库版本自动升级,并且有一套预设的规约,
不需要复杂的配置。Migrations可以写成SQL指令码,也可以写在Java程式码中,不仅支援Command Line和Java API,
还支援Build构建工具和Spring Boot等。同时在分散式环境下能够安全可靠地升级资料库,同时也支援失败恢复等。

为什么要使用Flyway

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

flyway工作原理

一言以蔽之:flyway通过历史记录表(flyway_schema_history)来记录版本历史。
每次随专案启动时将会自动扫描在resources/db/migration下的档案并查询flyway_schema_history判断是否为新增档案。
如果是新增的档案,则执行该迁移档案。如果不是,则忽略。

  1. 当flyway在一个空资料库执行时,它将直接建立一张预设名为flyway_schema_history的资料记录为空的历史记录表,这张表将被用来跟踪或记录资料库的状态。
  2. flyway将会开始扫描文件系统或专案classpath路径下的迁移档案。flyway按版本号顺序排列迁移档案,并按序执行,并更新历史记录表中的内容
  3. 当专案再次发版时,flyway会再次扫描迁移档案,然后将迁移文的版本号与历史记录表中的版本号进行对比。
    flyway会忽略版本号小于等于表中当前最大版本的迁移档案,剩余待执行迁移档案会按版本号升序执行。

并非真正忽略,而是会校验checksum值是否一致,以此来保证历史版本档案未被篡改

flyway实践

添加引用

1
2
3
4
<dependency>  <!-- 注意,这是springboot环境中,已经有版本了,所以无需添加,其余环境需要自己看情况 -->
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

添加配置

springboot为例

1
2
3
4
5
6
7
spring.flyway.enabled=true # 开启flyway,默认true
spring.flyway.baseline-on-migrate=true #当迁移时发现目标schema非空,而且带有没有后设资料的表时,是否自动执行基准迁移,预设false.
spring.flyway.locations=classpath:db/migration # sql文件地址,默认就是 classpath:db/migration
spring.flyway.table=dataease_version # 记录数据库记录的表的名称
spring.flyway.baseline-version=0 # 开始执行基准迁移时对现有的schema的版本打标签,默认值为1
spring.flyway.encoding=UTF-8 # 编码,默认就是UTF-8
spring.flyway.validate-on-migrate=false # 迁移是否校验,默认为true

添加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 会被忽略。

Flyway 将 SQL 文件分为 VersionedRepeatableUndo 三种:

  1. Versioned 用于版本升级, 每个版本有唯一的版本号并只能执行一次.
  2. Repeatable 可重复执行, 当 Flyway检测到 Repeatable 类型的 SQL 脚本的 checksum 有变动,
    Flyway 就会重新应用该脚本. 它并不用于版本更新, 这类的 migration 总是在 Versioned 执行之后才被执行。
  3. Undo 用于撤销具有相同版本的版本化迁移带来的影响。但是该回滚过于粗暴,过于机械化,一般不推荐使用。一般建议使用 Versioned 模式来解决。
  1. Prefix 可配置,前缀标识,默认值 V 表示 Versioned, R 表示 Repeatable, U 表示 Undo
  2. Version 标识版本号, 由一个或多个数字构成, 数字之间的分隔符可用点 . 或下划线 _
  3. Separator 可配置, 用于分隔版本标识与描述信息, 默认为两个下划线 __
  4. Description 描述信息, 文字之间可以用下划线 _ 或空格 分隔
  5. Suffix 可配置, 后续标识, 默认为 .sql

另一种sql文件夹风格

可以使用文件夹来区分,但是还是依照版本号规则来执行

最佳实践

语义化sql文件名字

前面给的例子中,都是用的v1,v2,v3这样的版本号,其实是非常不友好的,因为这样的话,我不知道我的语义化版本和我的sql脚本到底怎么对应,所以,这样是非常不好的,好的方式应该是
使用语义化版本来命名这些sql文件,这样约定下来,就非常清晰

补充

配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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