原文地址: "梁桂釗的博客" 博客地址: "http://blog.720ui.com" 歡迎關註公眾號:「服務端思維」。一群同頻者,一起成長,一起精進,打破認知的局限性。 今天,探討一個有趣的話題:我們可以通過 Git 來實現項目版本控制;通過 Jenkins 進行持續集成,那麼對於資料庫層面,我 ...
原文地址:梁桂釗的博客
歡迎關註公眾號:「服務端思維」。一群同頻者,一起成長,一起精進,打破認知的局限性。
今天,探討一個有趣的話題:我們可以通過 Git 來實現項目版本控制;通過 Jenkins 進行持續集成,那麼對於資料庫層面,我們仍然依賴於純手工運行 SQL 腳本,對此,我們在多環境(開發環境、測試環境、預發環境、生產環境)中如何確保其 SQL 腳本的最新性和正確性?
眾所周知,人工的操作非常容易出問題,我們應該讓程式幫忙自動進行管理和遷移。今天,筆者推薦一款開源的資料庫遷移工具 Flyway。
Flyway 不僅可以支持 MySQL,它也可以支持非常多其他的資料庫。
事實上,Spring Boot 已經完美整合了 Flyway。對此,我們可以非常便捷地使用它。首先,我們引入 Maven 依賴。(註意的是,我們項目中還需要 spring-boot-starter-jdbc、 mysql-connector-java 依賴)
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
此外,我們在 application.yml 中配置相關選項。Spring Boot 預設在 classpath://db/migration 目錄下掃描Migration。這裡,筆者通過 spring.flyway.locations 將其調整為 db/sql。
spring:
flyway:
enabled: true
baseline-on-migrate: true
locations: [classpath:db/sql]
當系統程式啟動時,它會自動創建 flyway_schema_history 文件。(當然,也可以自己手動創建)。這張表是 Flyway 的元數據表, 其保存著每次 migration 的記錄, 記錄包含 migration 腳本的版本號和 SQL 腳本的 checksum 值。當一個新的 SQL 腳本被掃描到後, Flyway 解析該 SQL 腳本的版本號, 並和 metadata 表對比, 如果該 SQL 腳本版本更新的話, 將在指定的 DB 上執行該 SQL 文件, 否則跳過該 SQL 文件。
CREATE TABLE `flyway_schema_history` (
`installed_rank` int(11) NOT NULL,
`version` varchar(50) DEFAULT NULL,
`description` varchar(200) NOT NULL,
`type` varchar(20) NOT NULL,
`script` varchar(1000) NOT NULL,
`checksum` int(11) DEFAULT NULL,
`installed_by` varchar(100) NOT NULL,
`installed_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`execution_time` int(11) NOT NULL,
`success` tinyint(1) NOT NULL,
PRIMARY KEY (`installed_rank`),
KEY `flyway_schema_history_s_idx` (`success`)
)
然後,我們在 db/sql 下手動創建一個初始化的 SQL 腳本:V1.1__INIT_DB.sql。
DROP TABLE IF EXISTS `tag`;
CREATE TABLE `tag` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`gmtCreate` date DEFAULT NULL,
`gmtModified` date DEFAULT NULL,
`title` varchar(32) DEFAULT NULL,
`parentId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
那麼,在程式再次啟動後,它會將其自動化發佈到資料庫中。
這裡,需要補充的知識點:Flyway 的版本比較規則。其採取左對齊原則,缺位用 0 代替。例如 1.1 比 1.0 版本高,1.1.1 比 1.1 版本高,而 1.1.01 和 1.1.1 版本一致。 並且,它們會按照版本排序且順序執行。
此外,Flyway 不僅支持 DDL,也同時支持 DML(insert、update、delete)等。因此,我們可以再創建一個 V1.2__INSERT_TAG_DATA.sql 文件來驗證一下。
INSERT tag(title, parentId) values('java', 0);
INSERT tag(title, parentId) values('spring', 0);
最後,我們在來一起探討下Flyway 支持常見類型的 migration:
- Versioned migrations:資料庫升級腳本
- Repeatable migrations:可重覆執行,當腳本 checksums 改變時會重新執行。
- prefix: 首碼標識,預設值 V 表示 Versioned, R 表示 Repeatable
- version: 標識版本號, 由一個或多個數字構成, 數字之間的分隔符可用點.或下劃線_
- separator: 用於分隔版本標識與描述信息, 預設為兩個下劃線__
- description: 描述信息, 文字之間可以用下劃線或空格分隔
- suffix: 後續標識, 預設為.sql
總結一下,Flyway 通過元數據(flyway_schema_history)幫忙我們自動化維護和管理資料庫的版本遷移。
寫在末尾
【服務端思維】:我們一起聊聊服務端核心技術,探討一線互聯網的項目架構與實戰經驗。讓所有孤軍奮戰的研發人員都找到屬於自己的圈子,一起交流、探討。在這裡,我們可以認知升級,連接頂級的技術大牛,連接優秀的思維方式,連接解決問題的最短路徑,連接一切優秀的方法,打破認知的局限。
更多精彩文章,盡在「服務端思維」!
本文由博客一文多發平臺 OpenWrite 發佈!