上文介绍了Liquibase,以及和SpringBoot的集成。除了Liquibase之外,还有一个组件Flyway也是经常被使用到的类似的数据库版本管理中间件。本文主要介绍Flyway, 以及SpringBoot集成Flyway。@pdai
需要了解Flyway和要解决的问题,以及一些基础概念,比如变迁(migrations),常用命令(commands)等。
Flyway是一款数据库迁移(migration)工具。简单点说,就是在你部署应用的时候,帮你执行数据库脚本的工具。Flyway支持SQL和Java两种类型的脚本,你可以将脚本打包到应用程序中,在应用程序启动时,由Flyway来管理这些脚本的执行,这些脚本被Flyway称之为migration。
PS: 本质上和liquibase机制一致。
按照verion的顺序(和数据库中的更新记录对比,找到未更新的),更新如下
更新记录如下
对于Flyway,对数据库的所有更改都称为变迁(migrations),等同于liquibase中的changeset。
在Flyway中变迁(migrations)定义的更细,包含如下三种:
这三种类型对应的格式如下:
(PS:撤销变迁(Undo Migrations)在收费版本中)
Flyway中的常用commands有哪些?什么含义?
Migrate: 是Flyway工作流的核心。它将扫描文件系统或类路径以查找可用的Migrate。它将把它们与已应用于数据库的Migrate进行比较。如果发现任何差异则迁移数据。
Clean: 清除掉对应数据库Schema中所有的对象,包括表结构,视图,存储过程等,clean操作在dev 和 test阶段很好用;(PS:不能用在product环境)
Info: 用于打印所有的Migrations的详细和状态信息,也是通过MetaData和Migrations完成的,可以快速定位当前的数据库版本;
Validate: 验证以及apply的Migrations是否有变更,默认开启的;原理是对比MetaData表与本地Migrations的checkNum值,如果值相同则验证通过,否则失败。
Undo: Migrate的反操作, 即回滚操作,这是收费功能
BaseLine:对已经存在数据库Schema结构的数据库一种解决方案。实现在非空数据库新建MetaData表,并把Migrations应用到该数据库;也可以应用到已有表结构的数据库中也可以实现添加Metadata表。
Repair:repair操作能够修复metaData表,该操作在metadata出现错误时很有用
这里主要介绍基于SpringBoot集成flyway来管理数据库的变更。
Maven 包的依赖,主要包含mysql驱动, JDBC(这里spring-boot-starter-data-jpa包含了jdbc包,当然直接引入jdbc包也行),以及flyway包。
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <dependency> <groupId>com.github.wenhao</groupId> <artifactId>jpa-spec</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-mysql</artifactId> <version>8.5.7</version> </dependency>
SpringBoot AutoConfig默认已经包含了对flyway的配置,在spring.flyway配置下
spring: datasource: url: jdbc:mysql://localhost:3306/test_db_flyway?useSSL=false&autoReconnect=true&characterEncoding=utf8 driver-class-name: com.mysql.cj.jdbc.Driver username: root password: bfXa4Pt2lUUScy8jakXf flyway: enabled: true encoding: UTF-8 # 可以支持多个location, 用','隔开 locations: classpath:db/migration # migrate是否校验 validate-on-migrate: true
在开发时,更多的配置可以从如下SpringBoot AutoConfig中找到。
这里我们准备两个Versioned Migration
DROP TABLE IF EXISTS `tb_user`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `tb_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_name` varchar(45) NOT NULL, `password` varchar(45) NOT NULL, `email` varchar(45) DEFAULT NULL, `phone_number` int(11) DEFAULT NULL, `description` varchar(255) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */;
LOCK TABLES `tb_user` WRITE; /*!40000 ALTER TABLE `tb_user` DISABLE KEYS */; INSERT INTO `tb_user` VALUES (1,'pdai','dfasdf','suzhou.daipeng@gmail.com',1212121213,'afsdfsaf','2021-09-08 17:09:15','2021-09-08 17:09:15'); /*!40000 ALTER TABLE `tb_user` ENABLE KEYS */; UNLOCK TABLES;
启动springBootApplication, 我们可以看到如下log
2022-04-13 07:56:56.122 INFO 86030 --- [ main] o.f.c.i.database.base.DatabaseType : Database: jdbc:mysql://localhost:3306/test_db_flyway (MySQL 8.0) 2022-04-13 07:56:56.220 INFO 86030 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.074s) 2022-04-13 07:56:56.245 INFO 86030 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `test_db_flyway`.`flyway_schema_history` ... 2022-04-13 07:56:56.270 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.282 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.292 INFO 86030 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `test_db_flyway`: << Empty Schema >> 2022-04-13 07:56:56.297 INFO 86030 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `test_db_flyway` to version "1.0 - Init DB" 2022-04-13 07:56:56.309 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Unknown table 'test_db_flyway.tb_user' (SQL State: 42S02 - Error Code: 1051) 2022-04-13 07:56:56.309 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.309 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.310 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. (SQL State: HY000 - Error Code: 3719) 2022-04-13 07:56:56.310 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.317 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Integer display width is deprecated and will be removed in a future release. (SQL State: HY000 - Error Code: 1681) 2022-04-13 07:56:56.317 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Integer display width is deprecated and will be removed in a future release. (SQL State: HY000 - Error Code: 1681) 2022-04-13 07:56:56.317 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. (SQL State: HY000 - Error Code: 3719) 2022-04-13 07:56:56.317 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.318 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.333 INFO 86030 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `test_db_flyway` to version "1.1 - Init Data" 2022-04-13 07:56:56.334 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.335 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Table storage engine for 'tb_user' doesn't have this option (SQL State: HY000 - Error Code: 1031) 2022-04-13 07:56:56.335 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.335 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 1 rows affected 2022-04-13 07:56:56.336 WARN 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Table storage engine for 'tb_user' doesn't have this option (SQL State: HY000 - Error Code: 1031) 2022-04-13 07:56:56.337 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.337 INFO 86030 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : 0 rows affected 2022-04-13 07:56:56.346 INFO 86030 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 2 migrations to schema `test_db_flyway`, now at version v1.1 (execution time 00:00.058s)
生成的flyway更新的记录,test_db_flyway
.flyway_schema_history
已经user表结构和数据
通过几个问题,进一步理解。
从Flyway对MySQL支持性,可以看出官方期望通过MySQL使用的大量基数获取更多的付费用户。
首先,如果你只是引入flyway-core:8.5.7的包时,会报如下错误
Caused by: org.flywaydb.core.api.FlywayException: Unsupported Database: MySQL 8.0 at org.flywaydb.core.internal.database.DatabaseTypeRegister.getDatabaseTypeForConnection(DatabaseTypeRegister.java:106) ~[flyway-core-8.5.7.jar:na] at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:76) ~[flyway-core-8.5.7.jar:na] at org.flywaydb.core.FlywayExecutor.execute(FlywayExecutor.java:147) ~[flyway-core-8.5.7.jar:na] at org.flywaydb.core.Flyway.migrate(Flyway.java:124) ~[flyway-core-8.5.7.jar:na] at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:66) ~[spring-boot-autoconfigure-2.5.3.jar:2.5.3] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.9.jar:5.3.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.9.jar:5.3.9] ... 18 common frames omitted
因为找不到内置的Datebase type
所以你应该引入的包是flyway-mysql:8.5.7,而有意思的是这个包中包含的flyway-core版本是7.7.3
然后我们看下官网对MySQL的支持性,这骚操作,5.7版本还需要使用企业版。就是为了收费,折腾...。
https://github.com/realpdai/tech-pdai-spring-demos