SpringBoot集成Flyway

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
注册配置 MSE Nacos/ZooKeeper,182元/月
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: Flyway:官方解释:Flyway 将 DevOps 扩展到您的数据库,以加速软件交付并确保代码质量。从版本控制到持续交付,Flyway 以应用程序交付流程为基础,实现数据库部署自动化。官方解释总是那么拗口和不说人话,当然通过加粗的关键字我们基本也能够了解到Flyway的功能特性。通俗来说,Flyway可以作为数据库迁移工具服务到我们的应用程序升级发布流程中,减少人为处理sql脚本带来的繁琐和易出错问题。例如,当我们的一个业务微服务从1.5.0升级到1.5.1的时候涉及到数据库的改动(DDL、DML)可以交给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属性

思考

  • 多数据源如何玩?

引用

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
9天前
|
消息中间件 Java Apache
SpringBoot集成RocketMq
RocketMQ 是一款开源的分布式消息中间件,采用纯 Java 编写,支持事务消息、顺序消息、批量消息、定时消息及消息回溯等功能。其优势包括去除对 ZooKeeper 的依赖、支持异步和同步刷盘、高吞吐量及消息过滤等特性。RocketMQ 具备高可用性和高可靠性,适用于大规模分布式系统,能有效保障消息传输的一致性和顺序性。
494 2
|
6月前
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
319 0
|
6月前
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
247 0
|
6月前
|
NoSQL Java 关系型数据库
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
271 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
3月前
|
前端开发
SpringBoot2.3.1集成Knife4j接口文档
SpringBoot2.3.1集成Knife4j接口文档
454 44
|
2月前
|
缓存 JSON 前端开发
第07课:Spring Boot集成Thymeleaf模板引擎
第07课:Spring Boot集成Thymeleaf模板引擎
383 0
第07课:Spring Boot集成Thymeleaf模板引擎
|
6月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
292 0
|
2月前
|
Java 关系型数据库 MySQL
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
341 2
|
2月前
|
分布式计算 Java 大数据
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
152 2
|
2月前
|
存储 人工智能 Java
Springboot集成AI Springboot3 集成阿里云百炼大模型CosyVoice2 实现Ai克隆语音(未持久化存储)
本项目基于Spring Boot 3.5.3与Java 17,集成阿里云百炼大模型CosyVoice2实现音色克隆与语音合成。内容涵盖项目搭建、音色创建、音频合成、音色管理等功能,适用于希望快速掌握Spring Boot集成语音AI技术的开发者。需提前注册阿里云并获取API Key。