知道的越多,不知道的就越多,業餘的像一棵小草!
編輯:業餘草
來源:https://www.xttblog.com/?p=5004
一、前言
Flyway 是一款開源的數據庫版本管理工具,它更傾向於規約優於配置的方式。Flyway 可以獨立於應用實現管理並跟蹤數據庫變更,支持數據庫版本自動升級,並且有一套默認的規約,不需要複雜的配置,Migrations 可以寫成 SQL 腳本,也可以寫在 Java 代碼中,不僅支持 Command Line 和 Java API,還支持 Build 構建工具和 Spring Boot 等,同時在分佈式環境下能夠安全可靠地升級數據庫,同時也支持失敗恢復等。
二、簡單介紹
# 2.1 主要特性
普通 SQL:純 SQL 腳本(包括佔位符替換)沒有專有的XML格式,沒有鎖定
無限制:使用 Java 代碼來進行一些高級數據操作
零依賴:只需運行在 Java6(及以上)和數據庫所需的 JDBC 驅動
約定優於配置:遷移時,自動查找系統文件和類路徑中的 SQL 文件或 Java 類
高可靠性:在集羣環境下進行數據庫升級是安全可靠的
雲支持:完全支持 Microsoft SQL Azure, Google Cloud SQL & App Engine、Heroku Postgres 和 Amazon RDS
自動遷移:使用 Flyway 提供的 API,讓應用啓動和遷移同時工作
快速失敗:損壞的數據庫或失敗的遷移可以防止應用程序啓動
數據庫清理:在一個數據庫中刪除所有的表、視圖、觸發器,而不是刪除數據庫本身
# 2.2 運行原理
當 Flyway 連接數據庫中的 schema 後,會先檢查是否已存在 flyway_schema_history 表,如果沒有則創建。該表用於跟蹤數據庫的狀態,如數據遷移的版本,遷移成功狀態等信息。
當 flyway_schema_history 存在後,Flyway 會掃描文件系統或應用中的 classpath 目錄的數據遷移文件,然後根據它們的版本號進行按序遷移,如下圖:
flyway_schema_history 表記錄的內容如下:
由於 flyway_schema_history 表中記錄了遷移的版本號,如果文件的版本號小於或等於標記爲當前版本的版本號,則忽略它們不執行。
上邊描述的內容或許對讀者來說還不夠直觀,那麼下面我們就開始進行實戰演練。
三、實戰
測試環境:Mysql5.7
新建一個 Maven 項目。
# 3.1 添加依賴
<!-- flyway -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
# 3.2 配置數據遷移文件
在項目的 src/main/resources 下創建 db/migration 目錄,該目錄下放置需要數據遷移的文件。
數據遷移文件名稱格式爲:V[version]__[name].sql。
注意:名稱中[version]和[name]之間是兩個下劃線!
本次測試新建名爲 V1__Create_person_table.sql 的文件,內容如下:
create table PERSON (
ID int not null,
NAME varchar(100) not null
);
版本 1 數據遷移的內容是創建一張 PERSON 表。
# 3.3 編碼
public class FlywayTest {
public static void main(String[] args) {
String url = "jdbc:mysql://127.0.0.1:3306/flyway?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false&serverTimezone=GMT%2B8";
String user = "root";
String password = "tiger";
Flyway flyway = Flyway.configure().dataSource(url, user, password).load();
// 創建 flyway_schema_history 表
// flyway.baseline();
// 刪除 flyway_schema_history 表中失敗的記錄
// flyway.repair();
// 檢查 sql 文件
// flyway.validate();
// 執行數據遷移
flyway.migrate();
// 刪除當前 schema 下所有表
// flyway.clean();
}
}
執行結果如下圖:
圖中,數據庫 flyway 中創建了 flyway_schema_history 表和 PERSON 表,數據成功遷移到指定數據庫中。
當系統升級時又需要做數據遷移,我們只需在 db/migration 目錄下再放置新版本的 sql 文件即可。
比如,我們再新建一個名爲 V2__Add_people.sql 文件,內容如下:
insert into PERSON (ID, NAME) values (1, 'Axel');
insert into PERSON (ID, NAME) values (2, 'Mr. Foo');
insert into PERSON (ID, NAME) values (3, 'Ms. Bar');
版本 2 的數據遷移內容是往 PERSON 表中插入 3 條數據。
再次執行上邊的程序,演示效果圖如下:
四、Spring Boot 整合
# 4.1 添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
# 4.2 application.yml
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/flyway?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false&serverTimezone=GMT%2B8
username: root
password: tiger
flyway:
enabled: true
# 禁止清理數據庫表
clean-disabled: true
# 如果數據庫不是空表,需要設置成 true,否則啓動報錯
baseline-on-migrate: true
# 與 baseline-on-migrate: true 搭配使用
baseline-version: 0
locations:
- classpath:db/migration/mysql(根據個人情況設置)
將需數據遷移的 sql 文件放置到 db/migration/mysql 目錄中,啓動 Spring Boot 項目即可運行 Flyway 進行數據遷移。
測試結果同上,此處不再張貼。
注意事項:
如果 flyway 不是項目初期引入,而是在數據庫已有表的情況下引入時必須設置 baseline-on-migrate: true,設置該配置啓動項目後,flyway 就會在數據庫中創建 flyway_schema_history 表,並且會往該表中插入一條 version = 1 的建表記錄,如果遷移數據有 V1__ 開頭的文件,掃描文件會忽略該文件不執行遷移,進而可能引發其他遷移數據出錯的問題。
以上邊的 2 個 sql 文件爲例進行演示,flyway 庫中已有一張 test 表,運行程序結果如下:
由於忽略了 V1__Create_person_table.sql ,庫中就不創建 PERSON 表,在遷移 V2__Add_people.sql 文件中的數據時必然失敗。
解決方案先刪除flyway_schema_history 表, 然後配置文件中設置 baseline-version: 0,或修改數據遷移文件版本名稱,最後再次啓動應用即可。