上文介紹了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','[email protected]',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版本還需要使用企業版。就是為了收費,折騰...。