• SpringBoot + Flyway,自动化实现数据库版本控制


    为什么使用Flyway

    最简单的一个项目是一个软件连接到一个数据库,但是大多数项目中我们不仅要处理我们开发环境的副本,还需要处理其他很多副本。例如:开发环境、测试环境、生产环境。想到数据库管理,我们立刻就能想到一系列问题

    • 如何快速收集执行脚本的清单

    • 执行的脚本总要人工执行,是否可以通过机器执行

    • 执行的脚本是否已经在数据库执行过

    • 执行的脚本是否全部在数据库中执行过

    • 执行的脚本如何回退

    • 如何初始化一个空数据库实例

    Flyway是一款数据库版本控制管理工具,它可以简单的、可靠的升级你的数据库。它能帮助解决上面的问题。 Flyway核心是记录所有版本演化和状态的MetaData,首次启动创建默认名为SCHEMA_VERSION的元素表。表中保存了版本,描述,要执行的sql脚本等信息。

    Flyway已经支持数据库包括:Oracle, SQL Server, SQL Azure, DB2, DB2 z/OS, MySQL (including Amazon RDS), MariaDB, Google Cloud SQL, PostgreSQL (including Amazon RDS and Heroku), Redshift, Vertica, H2, Hsql, Derby, SQLite, SAP HANA, solidDB, Sybase ASE and Phoeni

    官网链接:https://flywaydb.org/

    SpringBoot集成Flyway

    2.1 简单示例

    参考版本信息

    参考目录结构

    1.创建SpringBoot应用,并添加flyway-core依赖,本例中将实现初始化脚本到mysql数据库,因此同时引入了驱动依赖 mysql-connector-java

    1. <dependency>
    2.     <groupId>org.flywaydb</groupId>
    3.     <artifactId>flyway-core</artifactId>
    4.     <version>7.15.0</version>
    5. </dependency>

    参考pom.xml依赖如下

    1. <dependencies>
    2.     <dependency>
    3.         <groupId>org.springframework.boot</groupId>
    4.         <artifactId>spring-boot-starter</artifactId>
    5.     </dependency>
    6.     <dependency>
    7.         <groupId>org.springframework.boot</groupId>
    8.         <artifactId>spring-boot-starter-test</artifactId>
    9.         <scope>test</scope>
    10.     </dependency>
    11.     <dependency>
    12.         <groupId>org.springframework.boot</groupId>
    13.         <artifactId>spring-boot-starter-jdbc</artifactId>
    14.     </dependency>
    15.     <dependency>
    16.         <groupId>mysql</groupId>
    17.         <artifactId>mysql-connector-java</artifactId>
    18.         <version>8.0.28</version>
    19.     </dependency>
    20.     <dependency>
    21.         <groupId>org.flywaydb</groupId>
    22.         <artifactId>flyway-core</artifactId>
    23.         <version>7.15.0</version>
    24.     </dependency>
    25.     <dependency>
    26.         <groupId>org.junit.jupiter</groupId>
    27.         <artifactId>junit-jupiter-api</artifactId>
    28.         <version>5.8.2</version>
    29.         <scope>test</scope>
    30.     </dependency>
    31.     
    32. </dependencies>

    2.在application.properties中设置flyway信息

    1. server.port=7002
    2.  
    3. ##是否启动,默认开启
    4. spring.flyway.enabled = true
    5. ##脚本存放路径
    6. spring.flyway.locations = classpath:db/migration
    7. ##当flyway第一次运行时,会在我们对应的数据库中新建一个记录脚本运行情况的
    8. spring.flyway.table=flyway_schema_history
    9. ## flyway指向的数据库链接
    10. spring.datasource.url=jdbc:mysql://127.0.0.1:3306/runoob?useUnicode=true&characterEncoding=utf8
    11. ## 用户名
    12. spring.flyway.user=nacos
    13. ## 密码
    14. spring.flyway.password=nacos
    15. ## 数据库驱动
    16. spring.flyway.driver-class-name=com.mysql.cj.jdbc.Driver

    3.脚本整理

    将脚本整理到resource/db.migration路径下,例如

    参考SQL脚本信息如下

    1. //V1.20190621.1854__CREATE_PERSION_TABLE.sql脚本内容
    2. create table PERSON (
    3.     ID int not null,
    4.     NAME varchar(100not null
    5. );
    6.  
    7. //V1.20190621.1904__INIT_PERSION.sql 脚本内容
    8. insert into PERSON (ID, NAME) values (1'Axel');
    9. insert into PERSON (ID, NAME) values (2'Mr. Foo');
    10. insert into PERSON (ID, NAME) values (3'Ms. Bar');

    sql 目录中存放脚本文件,脚本名称命名方式

    • 版本化迁移:执行一遍,版本号唯一,有重复会报错: 格式:V+版本号 +双下划线+描述+结束符

    • 重复的迁移,不需要版本号,脚本发生变化启动就会执行:格式:R+双下划线+描述+结束符

    • 撤消迁移:格式:U+版本号 +双下划线+描述+结束符

    4.运行启动主类,运行日志如下,从日志中可以看到如下信息

    • 启动后正确链接到数据库runoob

    • 验证2个迁移脚本成功

    • 使用命令行的方式创建了一张名称为 flyway_schema_history 的记录表,这里要注意,所有脚本一旦执行了就会在 flyway_schema_history中创建记录, 如果出错引发问题,可以删除表中记录,反正启动的时候还会再执行,当然生产环境不建议此方法,但生产环境上部署的包都是验证过无问题的包也不会出现此问题

    • 执行了resource/db.migration 目录下的两个脚本,并执行成功

    1. INFO 190688 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 7.15.0 by Redgate
    2. INFO 190688 --- [           main] o.f.c.i.database.base.BaseDatabaseType   : Database: jdbc:mysql://127.0.0.1:3306/runoob (MySQL 5.7)
    3. INFO 190688 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 2 migrations (execution time 00:00.016s)
    4. INFO 190688 --- [           main] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table `runoob`.`flyway_schema_history` with baseline ...
    5. INFO 190688 --- [           main] o.f.core.internal.command.DbBaseline     : Successfully baselined schema with version: 1
    6. INFO 190688 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `runoob`: 1
    7. INFO 190688 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `runoob` to version "1.20190621.1854 - CREATE PERSION TABLE"
    8. INFO 190688 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `runoob` to version "1.20190621.1904 - INIT PERSION"
    9. INFO 190688 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 2 migrations to schema `runoob`, now at version v1.20190621.1904 (execution time 00:00.225s)

    停止服务后,重新运行日志如下,从日志中可以看到信息

    • 启动后正确链接到数据库runoob

    • 验证2个迁移脚本成功

    • 本次没有重复执行脚本, 日志中打印当前脚本编号20190621.1904, 即最后1次执行的脚本

    1. INFO 193184 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 7.15.0 by Redgate
    2. INFO 193184 --- [           main] o.f.c.i.database.base.BaseDatabaseType   : Database: jdbc:mysql://127.0.0.1:3306/runoob (MySQL 5.7)
    3. INFO 193184 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.024s)
    4. INFO 193184 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `runoob`: 1.20190621.1904
    5. INFO 193184 --- [           main] o.f.core.internal.command.DbMigrate      : Schema `runoob` is up to dateNo migration necessary.

    查看Mysql数据库

    2.2 常见问题

    1.Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s)

    1. Caused by: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) `runoob` but no schema history tableUse baseline() or set baselineOnMigrate to true to initialize the schema history table.
    2.  at org.flywaydb.core.Flyway$1.execute(Flyway.java:200) ~[flyway-core-7.15.0.jar:na]
    3.  at org.flywaydb.core.Flyway$1.execute(Flyway.java:170) ~[flyway-core-7.15.0.jar:na]
    4.  at org.flywaydb.core.Flyway.execute(Flyway.java:586) ~[flyway-core-7.15.0.jar:na]

    问题原因:第一执行的时候没有找到schema history table ,这张表其实就是application.properties文件中spring.flyway.table属性配置的表,因此要么使用命令创建一个或者在application.properties文件中设置 spring.flyway.baseline-on-migrate=true

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

    1. Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 5.7
    2.  at org.flywaydb.core.internal.database.DatabaseTypeRegister.getDatabaseTypeForConnection(DatabaseTypeRegister.java:106) ~[flyway-core-8.4.2.jar:na]
    3.  at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:75) ~[flyway-core-8.4.2.jar:na]
    4.  at org.flywaydb.core.FlywayExecutor.execute(FlywayExecutor.java:143) ~[flyway-core-8.4.2.jar:na]
    5.  at org.flywaydb.core.Flyway.migrate(Flyway.java:124) ~[flyway-core-8.4.2.jar:na]

    问题原因:flyway-core对数据库版本有要求,例如flyway-core的当前最高版本V8.4.3,不能使用 MySQL 5.7, 当flyway-core 降低到V7.15.0后 问题解决,所以匹配flyway-core和数据库版本后问题即可解决

    2.3 源码参考

    https://github.com/PNZBEIJINGL/springboot

    总结

    本文介绍了Springboot集成flyway方式

    • 使用Flyway之前部署脚本方式一般为开发人员按照顺序汇总数据库的升级脚, 然后DBA或者售后在生产库中按照顺序执行升级脚本。

    • 使用Flyway之后部署脚本方式就变更为开发人员将脚本构建到程序包中, 部署程序包后启动时Flyway自动执行脚本升级

  • 相关阅读:
    记一次doc、docx转html的过程
    MySQL项目实战——用户行为分析
    停止线程的方法
    编程笔记 Golang基础 045 math包
    深入剖析Java框架源码的设计之重载与重写、构造方法的区别详解
    仿游戏热血江湖游戏类25
    23、设计模式之访问者模式(Visitor)
    【算法】用动态规划求解背包问题
    初探C++ CRTP(奇异的递归模板模式)
    世界顶级写作比赛有哪些类型?
  • 原文地址:https://blog.csdn.net/m0_71777195/article/details/127667309