SpringBoot集成Flyway

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 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属性

思考

  • 多数据源如何玩?

引用

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
该文是一系列关于从零开始手写实现 Apache Tomcat 的教程概述。作者希望通过亲自动手实践理解 Tomcat 的核心机制。文章讨论了 Spring Boot 如何实现直接通过 `main` 方法启动,Spring 与 Tomcat 容器的集成方式,以及两者生命周期的同步原理。文中还提出了实现 Tomcat 的启发,强调在设计启动流程时确保资源的正确加载和初始化。最后提到了一个名为 mini-cat(嗅虎)的简易 Tomcat 实现项目,开源于 [GitHub](https://github.com/houbb/minicat)。
|
6天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
本文探讨了Spring Boot如何实现像普通Java程序一样通过main方法启动,关键在于Spring Boot的自动配置、内嵌Servlet容器(如Tomcat)以及`SpringApplication`类。Spring与Tomcat集成有两种方式:独立模式和嵌入式模式,两者通过Servlet规范、Spring MVC协同工作。Spring和Tomcat的生命周期同步涉及启动、运行和关闭阶段,通过事件和监听器实现。文章鼓励读者从实现Tomcat中学习资源管理和生命周期管理。此外,推荐了Netty权威指南系列文章,并提到了一个名为mini-cat的简易Tomcat实现项目。
|
4天前
|
Java 数据库连接 数据安全/隐私保护
springBoot集成token认证,最全Java面试知识点梳理
springBoot集成token认证,最全Java面试知识点梳理
|
6天前
|
NoSQL Java MongoDB
【MongoDB 专栏】MongoDB 与 Spring Boot 的集成实践
【5月更文挑战第11天】本文介绍了如何将非关系型数据库MongoDB与Spring Boot框架集成,以实现高效灵活的数据管理。Spring Boot简化了Spring应用的构建和部署,MongoDB则以其对灵活数据结构的处理能力受到青睐。集成步骤包括:添加MongoDB依赖、配置连接信息、创建数据访问对象(DAO)以及进行数据操作。通过这种方式,开发者可以充分利用两者优势,应对各种数据需求。在实际应用中,结合微服务架构等技术,可以构建高性能、可扩展的系统。掌握MongoDB与Spring Boot集成对于提升开发效率和项目质量至关重要,未来有望在更多领域得到广泛应用。
【MongoDB 专栏】MongoDB 与 Spring Boot 的集成实践
|
6天前
|
消息中间件 JSON Java
RabbitMQ的springboot项目集成使用-01
RabbitMQ的springboot项目集成使用-01
|
6天前
|
搜索推荐 Java 数据库
springboot集成ElasticSearch的具体操作(系统全文检索)
springboot集成ElasticSearch的具体操作(系统全文检索)
|
6天前
|
消息中间件 Java Spring
Springboot 集成Rabbitmq之延时队列
Springboot 集成Rabbitmq之延时队列
7 0
|
6天前
|
网络协议 Java Spring
Springboot 集成websocket
Springboot 集成websocket
12 0
|
6天前
|
XML Java 数据库
springboot集成flowable
springboot集成flowable
|
6天前
|
安全 Java 数据库连接
在IntelliJ IDEA中通过Spring Boot集成达梦数据库:从入门到精通
在IntelliJ IDEA中通过Spring Boot集成达梦数据库:从入门到精通