SpringBoot集成Flyway

[toc]

Flyway 简介

官方解释:Flyway 将 DevOps 扩展到您的数据库,以加速软件交付确保代码质量。从版本控制到持续交付,Flyway 以应用程序交付流程为基础,实现数据库部署自动化

官方解释总是那么拗口和不说人话,当然通过加粗的关键字我们基本也能够了解到Flyway的功能特性。

通俗来说,Flyway可以作为数据库迁移工具服务到我们的应用程序升级发布流程中,减少人为处理sql脚本带来的繁琐和易出错问题。

例如,当我们的一个业务微服务从1.5.0升级到1.5.1的时候涉及到数据库的改动(DDL、DML)可以交给Flyway处理,我们无需关心。

Flyway发展至今,已经只是一个代名词了,有FlywayDesktop,FlywaCLI,FlywayApi等等,老外擅长做生态,总之我们需要明确的是这个东西是服务于数据库迁移的就可以了。

Flyway工作流程

在实际项目开发中是否遇到这样的烦恼:

  • 开发环境没有问题,一升级,线上就出问题,一顿排查到深夜,最终发现是漏掉了一个sql脚本没有执行
  • 运维部署的时候突然问了一句本次升级有需要执行的sql吗?开发一脸懵,由于开发周期长,是否有sql,开发也忘记了
  • 由于开发人员多,每个人都把自己开发的功能涉及到的sql变更单独记录,到了交付测试的时候,sql一汇总,要么是有语法问题,就是执行顺序问题,反正是又得开发再整理一遍,部署预生产和生产同理
  • ……

Flyway就可以很优雅的解决上述问题。

  • 首先,在开发前,引入Flyway到项目中,并提前做好技术调研
  • 然后,在开发阶段,定义好本次迭代的版本号,创建好本次需要迁移的脚本文件名称到 resource 目录下,并昭告所有开发人员,sql统一记录到这个文件中
  • 最后,在开发完毕的时候,sql文件也就整理完毕了,此时只需要打包部署测试环境就好了,当程序在测试环境启动的时候,会自动执行resource目录下的数据库迁移脚本,并且如已经执行,不会重复执行
  • 需要注意的是,引入Flyway就要按照它的要求来,所有sql都需要记录在迁移脚本中,不可偷偷执行sql,不然部署其他环境就炸锅了

入门实践

以SpringBoot为例,SpringBoot官方推荐使用Flyway,引入pom将完成自动配置

pom


<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-mysql</artifactId>
</dependency>


<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
    <scope>runtime</scope>
</dependency>


  • 如果使用flyway版本在 8.2.0及之前,可以直接使用flyway-core(groupId=org.flywaydb;artifaceId=flyway-core;version=8.2.0)的依赖
  • flyway在8.2.1版本移除了mysql的默认支持,并创建了一个新的artifactId,即 flyway-mysql

yml


server:
  port: 9009
logging:
  level:
    com.ramble: debug
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.32:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: root
    password: LDr3SvzQPCjxSkf7
  jpa:
    show-sql: true
  flyway:
    baseline-on-migrate: true
    baseline-version: 0

  • baseline-on-migrate:是否自动创建迁移记录表,默认为false,需要设置为true,否则启动报错。flyway的原理就是依靠一个迁移记录表来管理各个版本的迁移脚本执行情况
  • baseline-version:迁移版本初始版本号,默认为1。

迁移sql脚本

在resources目录下创建db文件夹,然后在db文件夹下创建migration文件夹,最后创建V1.0.1__migration.sql的迁移脚本文件。

在V1.0.1__migration.sql 中写入如下sql:


INSERT INTO `user` (`id`, `name`, `state`) VALUES ('123', '漫步科技', 666);
  • classpath:/db/migration 目录为flyway默认的迁移脚本存放目录,可以通过flyway.locations进行配置
  • 迁移脚本文件名称:flyway的实现就是根据判断迁移记录表和迁移脚本文件名称来实现的。对于版本升级需要执行的sql,文件名称必须以“V”开头,后面跟版本号,再跟两个下划线,再跟自定义名称,最后跟“.sql”
  • V1.0.1__migration.sql:sql的内容就是在版本1.0.1中新增了一条数据

启动程序

启动程序之后库里将新增一个表 flyway_schema_history,此表是flyway自动生成的,同时会向user表中新增 一条数据。

启动日志,大概如下:

仅作参考



2023-07-30 16:11:25.072  INFO 16792 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 8.5.13 by Redgate
2023-07-30 16:11:25.072  INFO 16792 --- [           main] o.f.c.internal.license.VersionPrinter    : See what's new here: https://flywaydb.org/documentation/learnmore/releaseNotes#8.5.13
2023-07-30 16:11:25.072  INFO 16792 --- [           main] o.f.c.internal.license.VersionPrinter    : 
2023-07-30 16:11:25.078  INFO 16792 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-07-30 16:11:25.248  INFO 16792 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-07-30 16:11:25.278  INFO 16792 --- [           main] o.f.c.i.database.base.BaseDatabaseType   : Database: jdbc:mysql://192.168.1.32:3306/test (MySQL 8.0)
2023-07-30 16:11:25.493  INFO 16792 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.080s)
2023-07-30 16:11:25.625  INFO 16792 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `test`: 1.0.1
2023-07-30 16:11:25.896  INFO 16792 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `test` to version "1.0.2 - migration"
2023-07-30 16:11:26.199  INFO 16792 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 1 migration to schema `test`, now at version v1.0.2 (execution time 00:00.675s)

总结

上述实践演示了在SpringBoot中集成flyway,并做了一个简单的版本升级sql的迁移。

在实际开发中,只要每个迭代开始之前,创建好迁移文件,然后开发人员往里面填写sql。

在填写过程中,也可以看看其他人填写的sql,确保团队中所有人能大概知道别人的sql是否对自己有影响,还能互相检查一下是否有语法问题。

当阶段性开发完毕,直接升级程序就可以顺带迁移数据库了。

如果在操作过程中遇到异常,还可以通过删除flyway_schema_history 表记录或者修改迁移脚本名字来回滚或者重试操作。

本文仅作为入门参考,flyway实际可做的事情还有很多。写的不对的地方,欢迎大家勘误,没有写道的部分,也希望大家评论里讨论。

原理

  • 创建一个迁移记录表 flyway_schema_history
  • 应用启动的时候扫描resources下的特定sql文件
  • 将扫描到的sql文件进行排序
  • 与迁移记录表中的数据进行对比,并执行sql文件

常见问题

Unsupported Database

程序启动报如下错误


Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 8.0

当pom中 引入flyway-core并且版本高于8.2.0将引发此异常。

原因是从8.2.1开始,flyway对mysql的支持拆分出去了,使用flyway-mysql支持。

解决方案有两个:

  • 降低版本到8.2.0
  • 替换依赖为flyway-mysql

No migration necessary

一起配置正常,程序启动不报错,但是脚本就是没有执行,日志中一直提示没有需要迁移的必要(No migration necessary)。

可能的原因:迁移脚本没有放在classpath:db/migration 下,并且也没有配置 flyway.locations

解决办法:创建db文件夹,在db下创建migration文件夹;或者配置 flyway.locations属性

思考

  • 多数据源如何玩?

引用

请登录后发表评论

    没有回复内容