暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库版本管理,已经从困难变容易

七哥聊编程 2021-10-06
431

大家好,我是七哥。今天我给大家分享一个数据库迁移库 Flyway

这个单词有起飞的意思,我觉得它确实好用, Flyway集成到应用程序中可以带来最大的好处。什么好处呢?那我们先来看下它是用来解决七哥遇到的什么问题的吧。

0. 缘起

发现这个数据库迁移库的原因是因为我在从 Github 上面拉下来一个开源项目学习,这个项目涉及到数据库操作。在项目的使用说明文档中说明了脚本放在哪个目录,然后让我在运行项目之前先手动建表、插数据等这些操作。这个动作我其实就觉得挺烦的,为什么就不能直接拿来即用直接跑呢?

Flyway 就是用来干这件事的,只能修改下数据库的连接串为你的数据库,然后运行部署项目时就会自动执行相关脚本,并且能保证数据库脚本只执行一次,不会重复执行导致报错。接下来给大家详细介绍下,大家一定接着往下看。

1. Flyway简介

Flyway是一款数据库迁移(migration)工具。简单点说,就是在你部署应用的时候,帮你执行数据库脚本的工具。Flyway支持SQL和Java两种类型的脚本,你可以将脚本打包到应用程序中,在应用程序启动时,由Flyway来管理这些脚本的执行,这些脚本被Flyway称之为migration。

既然 Flyway 是用来管理项目中的数据库脚本的,我给大家列举一个目前我们一般的项目部署流程:

  • 开发人员将应用程序打包、按顺序汇总并整理数据库升级脚本
  • DBA拿到数据库升级脚本检查、备份、执行,以完成数据库升级
  • 应部署人员拿到应用部署包,备份、替换,以完成应用程序升级

用上 Flyway 之后的应用部署流程大概是这样的:

  • 开发人员将应用程序打包
  • 应部署人员拿到应用部署包,备份、替换,以完成应用程序升(Flyway将自动执行升级/备份脚本)

思考🤔:在我平时的团队开发中,我们的代码是有版本控制的,可以多人协作持续集成(工具也非常多)。但是数据库的脚本确实需要手动的去执行,团队内人多,你执行你的我执行我的,就会导致很多问题:

  • 这台机器上的数据库处于什么状态?
  • 此脚本是否已应用?
  • 测试环境的数据库表结构和生产是否一致?
  • 测试环境要新增一台应用实例,该如何搭建数据库,必备的数据和表结构如何快速同步?

所以工作中,经常听到测试小伙伴们抱怨,明明已经提测了,但是却出现 A环境正常运行,B环境就报错,找开发定位又花费很多时间。究其原因,大多数是因为数据库没有类似代码那样的版本控制自动化工具,导致管理混乱。

看到这里你应该能想到到 Flyway 这个数据库迁移库就是要解决这个问题的,可以帮我们根据数据库当前的状态,区分哪些脚本执行过,哪些没有执行,然后根据目标数据库的当前状态,决定应该执行哪些数据库脚本

那知道了它能帮我们干哪些事之后,我们就带着这个目标来看下 Flyway 的工作原理。

2. Flyway原理

最简单的情况是当我们将 Flyway 指向一个空数据库时,也就是将一个项目迁移到新的实例上,数据库也是新的,啥数据都没有。

假设我们有一个名为 Shiny 的项目,它连接到 Shiny DB。

空数据库

它将尝试获取数据库的历史变更记录。由于数据库是空的,Flyway 不会找到它,所以会 创建 变更记录表,默认情况下会创建一个名为 flyway_schema_history 的空表:

该表将用于跟踪数据库的状态。紧接着 Flyway 将开始扫描文件系统或应用程序的类路径以进行迁移。你可以用 Sql 或 Java 编写。

然后根据版本号对迁移进行排序并按顺序应用:

随着每次迁移的应用,数据库变更历史记录表会相应地更新:

根据上面的迁移记录,假如我们项目中有了新的数据库变更脚本,就可以根据迁移记录表中的版本号去和项目中扫描出的数据库脚本对比,如果版本号低于或者等于变更记录表中的成功记录,就会忽略不再执行。剩余的迁移是待处理的迁移:可用,但未应用。

然后它们按版本号排序并按顺序执行

执行成功后,更新变更记录表:flyway_schema_history

**就是这样!**每次需要变更数据库时,无论是 DDL 还是 DML,只需创建一个版本号高于当前版本号的新迁移。下次 Flyway 启动时,它会找到它并相应地升级数据库。

3. Flyway用法

这里我们直接给大家演示下 FLyway 最实用的用法,结合 Spring Boot 应用程序使用。

Flyway集成到应用程序中可以带来最大的好处。通过集成Flyway,您可以确保应用程序及其数据库始终是兼容的,不需要手动干预,最常见的就是数据库表不存在,配置表数据没有等等问题,因为这些问题没少被测试提 bug。Flyway检查数据库的版本,并在应用程序启动之前自动应用在当前环境未执行的迁移。

我们使用 Gradle 来构建应用程序,当然使用 Maven 也是一样的。

在构建说明文件加入依赖

  • 使用 Gradle 在 build.gradle 中加入依赖;
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'mysql:mysql-connector-java'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    compileOnly 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.flywaydb:flyway-core'  // 重点是这个依赖包引入
    annotationProcessor 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

}

  • 使用 Maven 在 pom.xml 中加入依赖;
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

  • 修改 application.yml 文件;
spring:
  profiles:
    active: production
management:
  endpoint:
    health:
      show-details: always
---
spring:
  profiles:
    include: production
  datasource:
    url: jdbc:mysql://localhost:3306/springroad?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: sevenluo
  jpa:
    database-platform: org.hibernate.dialect.MySQLDialect
    hibernate:
      ddl-auto: none
  flyway:
    baseline-on-migrate: true
    locations: classpath:db/mirration/

上面的 flyway.locations
指定了数据库脚本的存放路径,我们只需要按照命名规则迭代去增加就好了,下面是我增加的三个脚本所存放的路径:src/main/resources/db/migration/V1__inser_video.sql

所有的 migration 都需要遵守命名规范

  • Prefix(前缀):V表示版本化迁移,U表示撤销迁移,R表示可重复迁移;
  • Version(版本号):确保版本号唯一,flyway 按照版本号顺序执行。Repeatable 没有版本号,因为Repeatable Migrations会在内容改变时重复执行;
  • Separator(分隔符):__(两个下划线);
  • Description(描述):可以根据场景自行定义;

完整代码地址我放到 gitee 上了,国内访问速度更快、更稳定:https://gitee.com/isevenluo/spring-road/ ,点击文末 阅读原文可以直接到达。

4. 总结

通过今天的分享,想必大家又掌握了一个非常好用的工具库 Flyway。通过集成Flyway,你可以确保应用程序及其数据库始终是兼容的,不需要手动干预。

Flyway检查数据库的版本,并在应用程序启动前帮我们处理好所需要的数据库变更,恢复到最新的应用状态,这个功能在应用程序多环境部署或者迁移到新环境时太有用了,能减少我们太多排查定位数据库状态不一致导致bug的时间。让我们的工作可以高效起来 ~~

官方文档参考资料:https://flywaydb.org/documentation/


码字不易,觉得内容对你有帮助,希望你能花 0.1秒 点个赞哟~ 你小小的点赞永远是我持续创作的动力,谢谢你(疯狂比心)~

作者介绍: 七哥,一热爱技术的程序员,写文章也经常拍视频,专注于 Java 技术干货分享,愿望是陪家人平淡快乐的度过一生!


文章转载自七哥聊编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论