摘要
當我們的應用升級時往往會伴隨着數據庫表結構的升級,此時就需要遷移數據庫的表結構。一般我們會使用工具或者腳本來實現,手動操作畢竟有一定風險,要是能在應用啓動時自動升級數據庫表結構就好了!Flyway正是這麼一款工具,通過Flyway和SpringBoot結合使用,在應用啓動時就可以自動升級數據庫表結構,非常方便,推薦給大家!
Flyway簡介
Flyway是一款數據庫遷移工具,它讓數據庫遷移變得更加簡單。它能像Git一樣對數據庫進行版本控制,支持命令行工具、Maven插件、第三方工具(比如SpringBoot)等多種使用方式。
Flyway具有如下特點:
- 簡單:使用和學習簡單,通過不同版本的SQL腳本實現數據庫遷移。
- 專業:專注於數據庫遷移功能,你無需擔心有任何問題。
- 功能強大:支持多種數據庫,擁有大量的第三方工具,支持CI/DI。
相關概念
工作原理
使用Flyway時我們需要編寫好數據庫遷移的SQL腳本,比如 V1__Initial_Setup.sql中初始化了三種表,V2__First_Changes.sql中又新增了兩種表。Flyway會創建flyway_schema_history表,用於存儲這些SQL腳本的執行情況,從而對數據庫進行版本控制。當我們使用Flyway進行數據庫遷移時,Flyway會根據flyway_schema_history表中的記錄,自行決定需要執行哪些SQL腳本,從而實現數據庫遷移。
腳本命名規範
在創建Flyway的SQL腳本時,有些命名規範需要遵守,這些命名規範決定了Flyway執行腳本的順序和方式,可以先參考下面的示意圖。
爲了能被Flyway正確執行,SQL遷移腳本需要遵循如下規範:
- Prefix(前綴):V表示有版本號的數據庫遷移,U表示一些數據庫版本的回滾,R表示可重複執行的數據庫遷移;
- Version(版本號):Flyway會按照版本號的大小順序來執行數據庫遷移腳本;
- Separator(分隔符):命名時使用雙下劃線分隔符;
- Description(描述):用於描述該遷移腳本的具體操作說明;
- Suffix(後綴):表示.sql文件。
相關命令
- migrate:數據庫遷移命令,會根據設置好的SQL腳本直接將數據庫表升級至最新版本。
- clean:刪除數據庫中所有的表,千萬別在生產環境上使用。
- info:打印所有關於數據庫遷移的詳細信息和狀態信息。
- validate:驗證數據庫遷移是否可用。
- undo:對數據庫遷移進行回滾操作。
- baseline:以現有數據庫爲基準,創建flyway_schema_history表,大於基準版本的數據庫遷移纔會被應用。
- repair:修復flyway_schema_history表。
命令行工具
使用Flyway實現數據遷移有多種方式,我們先通過命令行工具的方法來體驗下Flyway的使用。
- 首先需要下載Flyway的命令行工具,下載社區版即可,下載地址:https://flywaydb.org/download
- 下載完成後進行解壓,解壓完成後目錄結構如下;
- 修改Flyway的配置文件/conf/flyway.conf,修改下數據庫配置即可;
flyway.url=jdbc:mysql://localhost:3306/flyway?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
flyway.user=root
flyway.password=root
- 在/sql目錄下添加SQL執行腳本,這裏添加創建ums_admin表的執行腳本V1.0.1__Create_ums_admin_table.sql;
CREATE TABLE `ums_admin`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`icon` varchar(500) DEFAULT NULL COMMENT '頭像',
`email` varchar(100) DEFAULT NULL COMMENT '郵箱',
`nick_name` varchar(200) DEFAULT NULL COMMENT '暱稱',
`note` varchar(500) DEFAULT NULL COMMENT '備註信息',
`create_time` datetime DEFAULT NULL COMMENT '創建時間',
`login_time` datetime DEFAULT NULL COMMENT '最後登錄時間',
`status` int(1) DEFAULT '1' COMMENT '帳號啓用狀態:0->禁用;1->啓用',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 8
DEFAULT CHARSET = utf8 COMMENT ='後臺用戶表';
- 使用flyway migrate命令進行數據遷移,此時我們會發現需要先使用flyway baseline命令創建保存遷移記錄的表flyway_schema_history纔行;
- 先使用flyway baseline命令,再使用flyway migrate命令,命令行會輸出執行成功的信息;
- 在\sql目錄下添加SQL執行腳本,給ums_admin表添加一些數據,執行腳本爲V1.0.2__Add_ums_admin.sql;
INSERT INTO ums_admin (username, PASSWORD, email, nick_name, STATUS)
VALUES ('test', '123456', '[email protected]', '測試賬號', 1);
INSERT INTO ums_admin (username, PASSWORD, email, nick_name, STATUS)
VALUES ('macro', '123456', '[email protected]', '普通賬號', 1);
INSERT INTO ums_admin (username, PASSWORD, email, nick_name, STATUS)
VALUES ('andy', '123456', '[email protected]', '普通賬號', 1);
- 我們可以使用flyway info命令查看flyway_schema_history表中的數據遷移記錄,可以發現1.0.2版本的更新還處於Pending狀態,使用flyway migrate命令後變爲Success;
- 我們可以創建可重複執行的SQL腳本,通常可以用來創建視圖、存儲過程、函數等,比如基於ums_admin表創建一個視圖,執行腳本爲R__Ums_admin_view.sql;
CREATE
OR REPLACE VIEW ums_admin_view AS
SELECT username,
PASSWORD,
email
FROM ums_admin;
- 使用flyway migrate命令可以重複執行(當R開頭的腳本有變更時),該腳本會在所有V開頭的腳本執行完成後執行;
- Flyway的回滾機制需要依賴SQL腳本,這裏創建U1.0.1__Create_ums_admin_table.sql和U1.0.2__Add_ums_admin.sql兩個回滾腳本;
# U1.0.1__Create_ums_admin_table.sql
DROP TABLE ums_admin
# U1.0.2__Add_ums_admin.sql
DELETE FROM ums_admin;
- 使用flyway undo命令可以執行回滾,很遺憾的是社區版本不支持回滾,看樣子數據庫升級之前還是得通過工具做好備份纔行!
Maven插件
Flyway也提供了Maven插件,插件所支持功能與命令行工具基本一致。
- 想要在Maven項目通過插件使用Flyway,首先需要在pom.xml中添加Flyway的插件並配置好數據庫連接信息;
<!--Flyway的Maven插件-->
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>7.3.2</version>
<configuration>
<url>jdbc:mysql://localhost:3306/flyway?serverTimezone=Asia/Shanghai</url>
<user>root</user>
<password>root</password>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
</dependencies>
</plugin>
- 在resouce目錄下創建db\migration目錄,將數據庫升級使用的SQL腳本放入進去;
- Flyway的Maven插件支持如下幾種命令;
- 雙擊flyway:info命令使用,輸出如下內容,此方式與命令行工具使用基本沒啥區別。
[INFO] --- flyway-maven-plugin:7.3.2:info (default-cli) @ mall-tiny-flyway ---
[INFO] Flyway Community Edition 7.3.2 by Redgate
[INFO] Database: jdbc:mysql://localhost:3306/flyway (MySQL 5.7)
[INFO] Schema version: 1.0.2
[INFO]
[INFO] +------------+---------+------------------------+----------+---------------------+----------+
| Category | Version | Description | Type | Installed On | State |
+------------+---------+------------------------+----------+---------------------+----------+
| | 1 | << Flyway Baseline >> | BASELINE | 2020-12-24 11:17:35 | Baseline |
| Versioned | 1.0.1 | Create ums admin table | SQL | 2020-12-24 11:17:42 | Success |
| Versioned | 1.0.2 | Add ums admin | SQL | 2020-12-24 11:33:40 | Success |
| Repeatable | | Ums admin view | SQL | 2020-12-24 11:33:40 | Success |
+------------+---------+------------------------+----------+---------------------+----------+
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.076 s
[INFO] Finished at: 2020-12-24T14:28:16+08:00
[INFO] Final Memory: 28M/286M
[INFO] ------------------------------------------------------------------------
Process finished with exit code 0
結合SpringBoot使用
由於SpringBoot官方已經支持了Flyway,所以Flyway結合SpringBoot使用非常簡單!
- 首先在pom.xml中添加Flyway相關依賴,注意無需添加Flyway的版本號:
<!--Flyway相關依賴-->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
- 修改配置文件application.yml,對數據源和Flyway進行配置;
spring:
datasource:
url: jdbc:mysql://localhost:3306/flyway?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
flyway:
# 啓用Flyway功能
enabled: true
# 禁用Flyway的clean命令,使用clean命令會刪除schema下的所有表
clean-disabled: true
# 設置Flyway的SQL腳本路徑
locations: classpath:db/migration
# 設置版本信息控制表名稱,默認flyway_schema_history
table: flyway_schema_history
# 在執行migrate命令時需要有flyway_schema_history表,通過baseline命令可以生成該表
baseline-on-migrate: true
# 指定baseline版本號,低於該版本的SQL腳本在migrate是不會執行
baseline-version: 1
# 設置字符編碼
encoding: UTF-8
# 不允許不按順序遷移
out-of-order: false
# 設置Flyway管控的schema,不設置的話爲datasourcel.url中指定的schema
schemas: flyway
# 執行migrate時開啓校驗
validate-on-migrate: true
- 最後直接運行SpringBoot應用,即可自動創建好對應的數據庫,控制檯會輸出如下信息。
2020-12-24 14:38:15.659 INFO 10716 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 6.4.1 by Redgate
2020-12-24 14:38:15.898 INFO 10716 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:mysql://localhost:3306/flyway (MySQL 5.7)
2020-12-24 14:38:15.972 INFO 10716 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 3 migrations (execution time 00:00.047s)
2020-12-24 14:38:15.988 INFO 10716 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `flyway`.`flyway_schema_history` with baseline ...
2020-12-24 14:38:16.106 INFO 10716 --- [ main] o.f.core.internal.command.DbBaseline : Successfully baselined schema with version: 1
2020-12-24 14:38:16.122 INFO 10716 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `flyway`: 1
2020-12-24 14:38:16.134 INFO 10716 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway` to version 1.0.1 - Create ums admin table
2020-12-24 14:38:16.248 INFO 10716 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway` to version 1.0.2 - Add ums admin
2020-12-24 14:38:16.281 INFO 10716 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway` with repeatable migration Ums admin view
2020-12-24 14:38:16.314 INFO 10716 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 3 migrations to schema `flyway` (execution time 00:00.206s)
總結
對比手動升級數據庫表結構,使用Flyway自動升級更有優勢。使用Flyway可以在我們升級應用時同時升級數據庫,由於社區版本目前不支持數據庫回滾,升級前做好備份是很有必要的。