【SpringBoot系列】使用Flyway管理数据库版本

【SpringBoot系列】使用Flyway管理数据库版本

码农世界 2024-05-29 后端 78 次浏览 0个评论

目录

1. 前言

2. Flyway 简介

3. Flyway 规则

4. Spring Boot 集成 Flyway

4.1 Flyway 依赖

4.2 Flyway 配置

4.3 Flyway 迁移实战

4.3.1 创建初始化脚本

4.3.2 创建变更脚本

5. Flyway最佳实践

6. 总结


【SpringBoot系列】使用Flyway管理数据库版本

1. 前言

我们都知道,Git/SVN 是代码界的版本控制工具,那么,Flyway 就是数据库界的版本控制工具,它可以记录数据库的变化记录。

可能很多公司都是通过人工去维护、同步数据库脚本,就比如我现在所在的公司。但经常会遇到疏忽而遗漏的情况,举个简单的例子:

我们在开发环境对某个表新增了一个字段,而提交测试时却忘了提交该 SQL 脚本,导致出现bug而测试中断,从而影响开发、测试工作效率。严重点的话,如果是在生产环境才发现问题,将会是重大线上事故,年终奖就别考虑了~ 

而有了 Flyway,我们可以按版本约定,统一管理所有的 SQL 脚本变更,在所有环境自动同步数据库,而无需人为手工控制,再也不用担心因数据库不同步而导致的各种环境问题了。绩效也杠杠滴 :)。

2. Flyway 简介

Flyway 是一个简单开源数据库版本控制器(约定大于配置),它支持 SQL、Java API 和命令行的运行方式,还提供一系列的插件支持(Maven、Gradle、ANT等)。

主要支持的命令:

  • Migrate(迁移)
  • Clean(清理所有配置的对象)
  • Info(显示迁移状态和细节)
  • Validate(验证迁移规则)
  • Undo(撤消最近的迁移)
  • Baseline(建立基线)
  • Repair(修复迁移历史表)

    Flyway 大受欢迎是因为它具有以下优点:

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

      官方网站:https://flywaydb.org/

      3. Flyway 规则

      Flyway 是如何比较两个 SQL 文件的先后顺序的呢?它采用 左对齐原则,缺位用0代替。举几个例子:

      1.0.0.1 比 1.0.0 版本高。

      1.0.10 比 1.0.9.4 版本高。

      1.0.0_1 比 1.0.0 版本高。

      1_0_0_1 比 1_0_0 版本高。

      1.0.10 和 1.0.010 版本号一样高,这是因为每个版本号部分的前导 0 会被忽略。

      Flyway 将 SQL 文件分为 Versioned 、Repeatable 和 Undo 三种:

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

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

        【SpringBoot系列】使用Flyway管理数据库版本

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

          4. Spring Boot 集成 Flyway

          Spring Boot 提供了对 Flyway 的自动配置,使我们可以开箱即用 Flyway 进行数据库版本控制。

          本文演示环境:

          • JDK 1.8
          • Spring Boot 2.7.18
          • MySQL 8.0

            4.1 Flyway 依赖

            spring-boot-dependencies 默认提供了对 Flyway 的版本管理,这里仅展示核心依赖:

            
            	
            		org.springframework.boot
            		spring-boot-starter-web
            	
            	
            		org.springframework.boot
            		spring-boot-starter-jdbc
            	
            	
            		com.mysql
            		mysql-connector-j
            		runtime
            	
            	
            		org.flywaydb
            		flyway-core
            	
            	
            	
            		org.flywaydb
            		flyway-mysql
            	
            

            4.2 Flyway 配置

            Spring Boot 默认提供了对 Flyway 的自动配置:

            org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration

            所以,在Spring Boot 项目中,我们仅仅只要提供对应的配置参数即可:

            # 数据库配置
            spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
            spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
            spring.datasource.username=root
            spring.datasource.password=root
            # 启动flyway migration, 默认为true
            spring.flyway.enabled=true
            # flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。
            spring.flyway.clean-disabled=true
            # SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration
            spring.flyway.locations[0]=classpath:db/migration
            #  metadata 版本控制历史表 默认 flyway_schema_history
            spring.flyway.table=flyway_schema_history
            # 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令
            # 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。
            spring.flyway.baseline-on-migrate=true

            Flyway 也是遵循 约定大于配置 的思想,更多 Flyway 的参数配置可以参考这个类:

            org.springframework.boot.autoconfigure.flyway.FlywayProperties

            4.3 Flyway 迁移实战

            4.3.1 创建初始化脚本

            首先,创建三个迁移脚本,相当于项目初始化:

            • V1.0.0_1__create_user.sql
            • V1.0.0_2__create_role.sql
            • R__init_data.sql

              请注意命名规则。

              具体 SQL 脚本内容就不贴上来了,完整的示例代码已提交 Gitee:

              https://gitee.com/haitao9481/springboot-flyway-demo

              1)首次启动

              从启动日志可以看出,已经迁移了3个脚本,并将当前版本更新到了 V1.0.0.2:

              【SpringBoot系列】使用Flyway管理数据库版本

              查看数据库,Flyway 历史表和业务表及数据都已经创建:

              【SpringBoot系列】使用Flyway管理数据库版本

              【SpringBoot系列】使用Flyway管理数据库版本 

              2)不修改再次启动 

              在不修改任何代码的情况下再次启动:

              【SpringBoot系列】使用Flyway管理数据库版本

              可以看到成功验证了 3 个迁移脚本,打印了当前版本号。因为当前没有比1.0.0.2更大的版本号,所以不会进行迁移。

              4.3.2 创建变更脚本

              我们再新增一个 SQL 脚本,相当于项目版本迭代过程中产生的 SQL 变更:

              • V1.0.1_1__alert_user.sql

                对user表新增一个字段:create_time。

                我们再次启动下:

                【SpringBoot系列】使用Flyway管理数据库版本

                成功迁移,当前版本来到了 V1.0.1.1。 

                5. Flyway最佳实践

                通过上面的介绍相信你很快就会使用 Flyway 进行数据库版本控制了。这里总结了一些在实际开发中的使用经验:

                1. 生产环境请务必设置 spring.flyway.clean-disabled=true。
                2. 尽量避免使用 Undo 模式。
                3. 开发版本号尽量根据团队来进行多层次的命名避免混乱。比如   Vx.y.z_{sequence}__{create|alert|feature|fix}_Description_Timestamp.sql ,这种命名可以获取更多脚本相关功能的信息。
                4. 多个系统公用一个数据库 schema 时配置 spring.flyway.table 为不同的系统设置不同的 metadata 表名而不使用缺省值 flyway_schema_history。

                6. 总结

                我们对 Flyway 数据库版本migration工具进行了介绍,并在Spring Boot应用中集成。Flyway 使用简单、自动化、开箱即用,这将大大规范我们的数据库管理,提高生产效率。

                本文完整示例代码已上传 Gitee:

                https://gitee.com/haitao9481/springboot-flyway-demo

                如果您觉得本文不错,欢迎转发分享,原创不易,Hyatt需要您的鼓励。

转载请注明来自码农世界,本文标题:《【SpringBoot系列】使用Flyway管理数据库版本》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,78人围观)参与讨论

还没有评论,来说两句吧...

Top