首页 专题 文章 代码 归档
SpringBoot的数据库迁移
2020.02.19 11:50 2020.02.19 12:03

1. 简介

作为一个以前写PHP的码农,其Laravel框架自带有数据库迁移,所以我一直在想SpringBoot有无数据库迁移。

有什么好处?

1、方便团队协作

2、开发环境和生产环境的数据库结构统一(随着项目的进行,肯定有数据库结构的变动)

经过网上查询资料,找到了:Flyway 这个库。

2. Flyway

2.1. 命令行工具

对于 SpringBoot 项目开发, 其实不需要专门安装 flyway 命令行工具和 maven 插件, SpringBoot 启动就会自动执行 DB migrate 操作. 对于其他的 flyway 操作, 就需要使用命令行工具或 maven 插件了.

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

2.2. Maven插件

地址:https://mvnrepository.com/artifact/org.flywaydb/flyway-maven-plugin

<plugin>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <version>6.2.3</version>
</plugin>

maven插件命令:mvn flyway:migrate

2.3. 工作原理

flyway 需要在 DB 中先创建一个 metdata 表 (缺省表名为 flyway_schema_history), 在该表中保存着每次 migration 的记录, 记录包含 migration 脚本的版本号和 SQL 脚本的 checksum 值.

当一个新的 SQL 脚本被扫描到后, Flyway解析该 SQL 脚本的版本号, 并和 metadata 表已 apply 的的 migration 对比, 如果该 SQL 脚本版本更新的话, 将在指定的 DB 上执行该 SQL 文件, 否则跳过该 SQL 文件.


两个 flyway 版本号的比较, 采用左对齐原则, 缺位用 0 代替. 举例如下:

  • 1.2.9.4 比 1.2.9 版本高.
  • 1.2.10 比 1.2.9.4 版本高.
  • 1.2.10 和 1.2.010 版本号一样高, 每个版本号部分的前导 0 会被忽略.

Flyway SQL 文件可以分为两类: Versioned 和 Repeatable.

Versioned migration 用于版本升级, 每个版本有唯一的版本号并只能 apply 一次.

Repeatable migration 是指可重复加载的 migration, 一旦 SQL 脚本的 checksum 有变动, flyway 就会重新应用该脚本. 它并不用于版本更新, 这类的 migration 总是在 versioned migration 执行之后才被执行.


默认情况下, Migration SQL的命名规则如下图:

截图-1582082956

其中的文件名由以下部分组成,除了使用默认配置外,某些部分还可自定义规则.

  • prefix: 可配置,前缀标识,默认值 V 表示 Versioned, R 表示 Repeatable
  • version: 标识版本号, 由一个或多个数字构成, 数字之间的分隔符可用点.或下划线_
  • separator: 可配置, 用于分隔版本标识与描述信息, 默认为两个下划线__
  • description: 描述信息, 文字之间可以用下划线或空格分隔
  • suffix: 可配置, 后续标识, 默认为.sql

flyway 的 metadata 表结果如下:

CREATE TABLE  flyway_schema_history
    (
        installed_rank INT NOT NULL,
        version VARCHAR(50),
        description VARCHAR(200) NOT NULL,
        type VARCHAR(20) NOT NULL,
        script VARCHAR(1000) NOT NULL,
        checksum INT,
        installed_by VARCHAR(100) NOT NULL,
        installed_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        execution_time INT NOT NULL,
        success TINYINT(1) NOT NULL,
        PRIMARY KEY (installed_rank),
        INDEX flyway_schema_history_s_idx (success)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

flyway核心包:(flyway 其实仅依赖 spring-boot-starter-jdbc 包)

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>6.2.3</version>
</dependency>

2.4. 一些配置

spring:
  ## 设定 flyway 属性
  flyway:
    #    flyway 的 clean 命令会删除指定 schema 下的所有 table, 杀伤力太大了, 应该禁掉.
    clean-disabled: true
    #    禁用/启用flyway
    enabled: true
    #    设定 SQL 脚本的目录,多个路径使用逗号分隔, 比如取值为 classpath:db/migration,filesystem:/sql-migrations
    locations: classpath:db/migration
    #    如果指定 schema 包含了其他表,但没有 flyway schema history 表的话, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令.
    baseline-on-migrate: true
    #    指定 baseline 的版本号,缺省值为 1, 低于该版本号的 SQL 文件, migrate 的时候被忽略.
    baseline-version: 1
    #    sql文件编码
    encoding: UTF-8
    #    设定 flyway 的 metadata 表名, 缺省为 flyway_schema_history
    table: flyway_schema_history_myapp
    #    开发环境最好开启 outOfOrder, 生产环境关闭 outOfOrder . 
    out-of-order: true

3. Flyway最佳实践

1、在resources/db/migration 新建SQL文件

2、SQL文件名是:

  • V0.0.1__init_table.sql
  • V0.0.2__add_column.sql

tips:前面两个"__"

3、前面说了,out-of-order: true开发环境开启,生产环境关闭。

那么关闭了,我们如何手动在生产环境迁移数据库?

很多方法,其一是通过Maven插件命令:

mvn flyway:migrate -Dflyway.url=... -Dflyway.user=... -Dflyway.password=...

需要添加配置:-Dflyway.url=... -Dflyway.user=... -Dflyway.password=...

不然是会报错的!

结果:

截图-1582084985


至此,整合完毕!

截图-1582084227

本节阅读完毕! (分享
二维码图片 扫描关注我们哟