知識準備
需要了解Flyway和要解決的問題,以及一些基礎概念,比如變遷(migrations),常用命令(commands)等。
什么是Flyway? 要解決什么問題?
Flyway是一款數(shù)據(jù)庫遷移(migration)工具。簡單點說,就是在你部署應用的時候,幫你執(zhí)行數(shù)據(jù)庫腳本的工具。Flyway支持SQL和JAVA兩種類型的腳本,你可以將腳本打包到應用程序中,在應用程序啟動時,由Flyway來管理這些腳本的執(zhí)行,這些腳本被Flyway稱之為migration。
PS: 本質(zhì)上和liquibase機制一致。
按照verion的順序(和數(shù)據(jù)庫中的更新記錄對比,找到未更新的),更新如下
更新記錄如下
Flyway中的變遷(migrations)
對于Flyway,對數(shù)據(jù)庫的所有更改都稱為變遷(migrations),等同于liquibase中的changeset。
在Flyway中變遷(migrations)定義的更細,包含如下三種:
- 版本變遷(Versioned Migrations): 每個版本執(zhí)行一次,包含有版本、描述和校驗和;常用于創(chuàng)建,修改,刪除表;插入,修改數(shù)據(jù)等
- 撤銷變遷(Undo Migrations): 版本變遷(Versioned Migrations)的反操作。
- 可重復變遷(Repeatable Migrations): 可以執(zhí)行多次,包含描述和校驗和(沒有版本);主要用于視圖,存儲過程,函數(shù)等
這三種類型對應的格式如下:
- 前綴: V 代表版本變遷(Versioned Migrations), U 代表撤銷變遷(Undo Migrations), R 代表可重復變遷(Repeatable Migrations)
- 版本號: 唯一的版本號,比如V1.0.1
- 分隔符: __ (兩個下劃線)
- 描述信息: 描述信息
- 后綴: .sql
(PS:撤銷變遷(Undo Migrations)在收費版本中)
Flyway中常用命令
Flyway中的常用commands有哪些?什么含義?
Migrate: 是Flyway工作流的核心。它將掃描文件系統(tǒng)或類路徑以查找可用的Migrate。它將把它們與已應用于數(shù)據(jù)庫的Migrate進行比較。如果發(fā)現(xiàn)任何差異則遷移數(shù)據(jù)。
Clean: 清除掉對應數(shù)據(jù)庫Schema中所有的對象,包括表結(jié)構,視圖,存儲過程等,clean操作在dev 和 test階段很好用;(PS:不能用在product環(huán)境)
Info: 用于打印所有的Migrations的詳細和狀態(tài)信息,也是通過MetaData和Migrations完成的,可以快速定位當前的數(shù)據(jù)庫版本;
Validate: 驗證以及Apply的Migrations是否有變更,默認開啟的;原理是對比MetaData表與本地Migrations的checkNum值,如果值相同則驗證通過,否則失敗。
Undo: Migrate的反操作, 即回滾操作,這是收費功能
BaseLine:對已經(jīng)存在數(shù)據(jù)庫Schema結(jié)構的數(shù)據(jù)庫一種解決方案。實現(xiàn)在非空數(shù)據(jù)庫新建MetaData表,并把Migrations應用到該數(shù)據(jù)庫;也可以應用到已有表結(jié)構的數(shù)據(jù)庫中也可以實現(xiàn)添加Metadata表。
Repair:repair操作能夠修復metaData表,該操作在metadata出現(xiàn)錯誤時很有用
簡單示例
這里主要介紹基于SpringBoot集成flyway來管理數(shù)據(jù)庫的變更。
POM依賴
Maven 包的依賴,主要包含MySQL驅(qū)動, 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>
yml配置
SpringBoot AutoConfig默認已經(jīng)包含了對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
在開發(fā)時,更多的配置可以從如下SpringBoot AutoConfig中找到。
Migrate配置
這里我們準備兩個Versioned Migration
- V1.0__Init_DB.sql
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 */;
- V1.1__Init_Data.sql
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
已經(jīng)user表結(jié)構和數(shù)據(jù)
進一步理解
通過幾個問題,進一步理解。
MySQL的支持性問題
從Flyway對MySQL支持性,可以看出官方期望通過MySQL使用的大量基數(shù)獲取更多的付費用戶。
首先,如果你只是引入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
因為找不到內(nèi)置的Datebase type
所以你應該引入的包是flyway-mysql:8.5.7,而有意思的是這個包中包含的flyway-core版本是7.7.3
然后我們看下官網(wǎng)對MySQL的支持性,這騷操作,5.7版本還需要使用企業(yè)版。就是為了收費,折騰...。
示例源碼
https://github.com/realpdai/tech-pdai-spring-demos
更多內(nèi)容
告別碎片化學習,無套路一站式體系化學習后端開發(fā): Java 全棧知識體系(https://pdai.tech)