Spring Boot 集成 Flyway 实现数据库版本控制

在项目迭代开发中,难免会有更新数据库 Schema 的情形,好比添加新表、在表中增添字段或者删除字段等,那么当我对数据库举行一系列操作后,若何快速地在其他同事的电脑上同步?若何在测试/生产服务器上快速同步?

Spring Boot 集成 Flyway 实现数据库版本控制

每次发版的时刻,由于人人都可能有 sql 更改情形,这样就会有以下痛点:

  • 遗忘某些 sql 修改
  • 每个开发人员的 sql 的执行顺序问题
  • 重复更新
  • 需要手动去数据库执行剧本

以上问题以及痛点可以通过 Flyway 工具来解决,Flyway 可以实现自动化的数据库版本治理,而且能够纪录数据库版本更新纪录。

Flyway 简介

Flyway 是独立于数据库的应用、治理并跟踪数据库调换的数据库版本治理工具。用通俗的话讲,Flyway 可以像 Git 治理不同人的代码那样,治理不同人的 sql 剧本,从而做到数据库同步,更多的信息可以在 Flyway 的官网上举行阅读学习。

另外 Flyway 支持许多关系数据库,详细如下所示:

Spring Boot 集成 Flyway 实现数据库版本控制

下面我们在 Spring Boot 中集成 Flyway 来实现数据库版本控制。

Spring Boot 集成 Flyway

首先建立一个 SpringBoot 项目,然后在 pom.xml 加入如下依赖集成 Flyway:

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>5.2.4</version>
</dependency>

然后在 application.yml 中写入 mysql 的设置及 Flyway 的相关设置(Flyway locations 默认读取当前项目下的 resources/db/migration 目录)

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123

spring.flyway.locations=classpath:/db/migration/

接下来,在 resources/db/migration 目录下建立需要执行的 SQL 剧本即可。

其中,SQL 剧本命名规范如下:

Spring Boot 集成 Flyway 实现数据库版本控制

  • Prefix 前缀:V 代表版本迁徙,U 代表打消迁徙,R 代表可重复迁徙
  • Version 版本号:版本号通常 . 和整数组成
  • Separator 分开符:牢固由两个下划线 __ 组成
  • Description 形貌:由下划线分开的单词组成,用于形貌本次迁徙的目的
  • Suffix 后缀:若是是 SQL 文件那么牢固由 .sql 组成,若是是基于 Java 类则默认不需要后缀

那么,我们根据命名规范在 resources/db/migration 目录下,建立 V1.0__init_db.sql SQL 迁徙剧本,详细内容如下:

Jmeter系列(10)- 阶梯加压线程组Stepping Thread Group详解

DROP TABLE IF EXISTS `user` ;

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '岁数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` (`id`, `name`, `age`) VALUES ('1', 'wupx', '18');

最后启动项目,执行日志如下所示:

2020-05-07 12:41:29.126  INFO 13732 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 5.2.4 by Boxfuse
2020-05-07 12:41:29.236  INFO 13732 --- [           main] o.f.c.internal.database.DatabaseFactory  : Database: jdbc:mysql://localhost:3306/test (MySQL 5.5)
2020-05-07 12:41:29.287  INFO 13732 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 1 migration (execution time 00:00.009s)
2020-05-07 12:41:29.330  INFO 13732 --- [           main] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table: `test`.`flyway_schema_history`
2020-05-07 12:41:29.479  INFO 13732 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `test`: << Empty Schema >>
2020-05-07 12:41:29.480  INFO 13732 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `test` to version 1.0 - init db
2020-05-07 12:41:29.481  WARN 13732 --- [           main] o.f.c.i.s.DefaultSqlScriptExecutor       : DB: Unknown table 'user' (SQL State: 42S02 - Error Code: 1051)
2020-05-07 12:41:29.631  INFO 13732 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 1 migration to schema `test` (execution time 00:00.301s)

从启动日志中可以看出,Flyway 监测到需要运行版本剧原本初始化数据库,因此执行了 V1.0__init_db.sql 剧本,从而建立了 user 表,另外还自动建立了 flyway_schema_history 表,用于纪录所有版本演化和状态,其表结构如下(以 MySQL 为例):

Field Type Null Key Default
version_rank int(11) NO MUL NULL
installed_rank int(11) NO MUL NULL
version varchar(50) NO PRI NULL
description varchar(200) NO NULL
type varchar(20) NO NULL
script varchar(1000) NO NULL
checksum int(11) YES NULL
installed_by varchar(100) NO NULL
installed_on timestamp NO CURRENT_TIMESTAMP
execution_time int(11) NO NULL
success tinyint(1) NO MUL NULL

查询 flyway_schema_history 表,发现增添了一条版本号为 1.0 的,使用 V1.0__init_db.sql 迁徙剧本的纪录。

mysql> SELECT * FROM flyway_schema_history;
+----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description | type | script            | checksum   | installed_by | installed_on        | execution_time | success |
+----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+
|              1 | 1.0     | init db     | SQL  | V1.0__init_db.sql | 1317299633 | root         | 2020-05-07 12:41:29 |             97 |       1 |
+----------------+---------+-------------+------+-------------------+------------+--------------+---------------------+----------------+---------+

再去查询 user 表,发现 sql 剧本中的数据也插入乐成了。

mysql> SELECT * FROM user;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | wupx |  18 |
+----+------+-----+

接下来再次运行项目,效果如下:

2020-05-07 15:34:49.843  INFO 41880 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 5.2.4 by Boxfuse
2020-05-07 15:34:49.981  INFO 41880 --- [           main] o.f.c.internal.database.DatabaseFactory  : Database: jdbc:mysql://localhost:3306/test (MySQL 5.5)
2020-05-07 15:34:50.036  INFO 41880 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 1 migration (execution time 00:00.013s)
2020-05-07 15:34:50.043  INFO 41880 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `test`: 1.0
2020-05-07 15:34:50.043  INFO 41880 --- [           main] o.f.core.internal.command.DbMigrate      : Schema `test` is up to date. No migration necessary.

从日志中可以看出,Flyway 发现一个迁徙剧本,也就是 V1.0__init_db.sql,经由判断已经到达最新版本 1.0,无需执行迁徙。

接下来,我们在 V1.0__init_db.sql 迁徙剧本中添加一条 INSERT 操作:INSERT INTO user (id, name, age) VALUES ('2', 'huxy', '18'); ,再次启动项目,会报如下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Validate failed: Migration checksum mismatch for migration version 1.0
-> Applied to database : 1317299633
-> Resolved locally    : -1582367361

这个错误的缘故原由就是 Flyway 会给剧本盘算一个 checksum 保留在数据库中,用于在之后运行过程中对比 sql 文件是否有转变,若是发生了转变,则会报错,也就防止了误修改剧本导致发生问题。

总结

Flyway 可以有用改善数据库版本治理方式,而且是一款 Java 开源的数据库迁徙治理工具,具有轻巧小巧的特点,可以无门槛快速集成到项目中,若是项目中还未使用,不防实验一下,想领会更多的可以去官网查看文档学习。

本文的完整代码在 https://github.com/wupeixuan/SpringBoot-Learndatabase-version-control 目录下。

最好的关系就是相互成就,人人的在看、转发、留言三连就是我创作的最大动力。

参考

https://flywaydb.org/

https://github.com/wupeixuan/SpringBoot-Learn

原创文章,作者:870t新闻网,如若转载,请注明出处:https://www.870t.com/archives/7854.html