Spring Boot 2 實戰(zhàn):使用 Flyway 管理你數(shù)據(jù)庫的版本變更

1. 前言

隨著項目的不斷迭代,數(shù)據(jù)庫表結構根资、數(shù)據(jù)都在發(fā)生著變化憾朴。甚至有的業(yè)務在多環(huán)境版本并行運行。數(shù)據(jù)為王的時代荞雏,管理好數(shù)據(jù)庫的版本也成為了迫切的需要。如何能做到像 Git 之類的版本控制工具來管理數(shù)據(jù)庫平酿?Java 項目中常用 FlywayLiquibase 來管理數(shù)據(jù)庫版本凤优。其中 Flyway 相對來說比較受歡迎。

2. Flyway 的特點

Flyway 大受歡迎是因為它具有以下優(yōu)點:

  • 簡單 非常容易安裝和學習蜈彼,同時遷移的方式也很容易被開發(fā)者接受筑辨。
  • 專一 Flyway 專注于搞數(shù)據(jù)庫遷移、版本控制而并沒有其它副作用幸逆。
  • 強大 專為連續(xù)交付而設計棍辕。讓Flyway在應用程序啟動時遷移數(shù)據(jù)庫暮现。

3. Flyway 的工作機制

Flyway 需要在 DB 中先創(chuàng)建一個 metadata 表 (缺省表名為 flyway_schema_history), 在該表中保存著每次 migration (遷移)的記錄, 記錄包含 migration 腳本的版本號和 SQL 腳本的 checksum 值。下圖表示了多個數(shù)據(jù)庫版本楚昭。

對應的 metadata 表記錄:

installed_rank version description type script checksum installed_by installed_on execution_time success
1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true
2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true

Flyway 掃描文件系統(tǒng)或應用程序的類路徑讀取 DDLDML 以進行遷移栖袋。根據(jù)metadata 表進行檢查遷移。如果腳本聲明的版本號小于或等于標記為當前版本的版本號之一抚太,將忽略它們塘幅。其余遷移是待處理遷移:可用,但未應用尿贫。最后按版本號對它們進行排序并按順序執(zhí)行 并將執(zhí)行結果寫入 metadata 表电媳。

對應的 metadata 表記錄:

installed_rank version description type script checksum installed_by installed_on execution_time success
1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true
2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true
3 2.1 Refactoring JDBC V2_1__Refactoring axel 2016-02-10 17:45:05.4 251 true

Flyway 支持命令行(需要下載命令行工具)和 Java Api ,也支持構建工具 MavenGradle 庆亡。這里我們將目光放在 Java Api 上匾乓。

3. Flyway 的規(guī)則

Flyway 是如何比較兩個 SQL 文件的先后順序呢?它采用 采用左對齊原則, 缺位用 0 代替 又谋。舉幾個例子:

1.0.1.1 比 1.0.1 版本高拼缝。

1.0.10 比 1.0.9.4 版本高。

1.0.10 和 1.0.010 版本號一樣高, 每個版本號部分的前導 0 會被忽略搂根。

FlywaySQL 文件分為 Versioned 珍促、RepeatableUndo 三種:

  • Versioned 用于版本升級, 每個版本有唯一的版本號并只能執(zhí)行一次.
  • Repeatable 可重復執(zhí)行, 當 Flyway檢測到 Repeatable 類型的 SQL 腳本的 checksum 有變動, Flyway 就會重新應用該腳本. 它并不用于版本更新, 這類的 migration 總是在 Versioned 執(zhí)行之后才被執(zhí)行。
  • Undo 用于撤銷具有相同版本的版本化遷移帶來的影響剩愧。但是該回滾過于粗暴猪叙,過于機械化,一般不推薦使用仁卷。一般建議使用 Versioned 模式來解決穴翩。

這三種的命名規(guī)則如下圖:

naming.png
  • Prefix 可配置,前綴標識锦积,默認值 V 表示 Versioned, R 表示 Repeatable, U 表示 Undo
  • Version 標識版本號, 由一個或多個數(shù)字構成, 數(shù)字之間的分隔符可用點 . 或下劃線 _
  • Separator 可配置, 用于分隔版本標識與描述信息, 默認為兩個下劃線 __
  • Description 描述信息, 文字之間可以用下劃線 _ 或空格 分隔
  • Suffix 可配置, 后續(xù)標識, 默認為 .sql

4. Spring Boot 集成 Flyway

Spring Boot 提供了對 Flyway 的自動配置 芒帕。使我們可以開箱即用 Flyway 進行數(shù)據(jù)庫版本控制。

4.1 Flyway 依賴

你只需要引入依賴:

      <!-- 無需版本號 -->
 <dependency>
      <groupId>org.flywaydb</groupId>
      <artifactId>flyway-core</artifactId>
 </dependency>      

當然你要集成你的相關數(shù)據(jù)庫環(huán)境丰介。這里我們采用 H2 數(shù)據(jù)庫來演示背蟆,其它數(shù)據(jù)庫同理只不過方言不同。不熟悉 H2 數(shù)據(jù)庫的可參閱我的專題文章 Spring Boot 2 實戰(zhàn):H2數(shù)據(jù)庫集成以及使用 哮幢。

4.2 Flyway 配置

為了直觀的講解配置带膀,首先在 Spring Boot 配置文件 application.yml 我們配置 H2 數(shù)據(jù)庫為:

 spring:
   datasource:
     #  h2 驅動
     driver-class-name: org.h2.Driver
     # h2  數(shù)據(jù)庫 持久化到磁盤D:/h2 庫名: flyway  mysql模式
     url: jdbc:h2:file:D:/h2/flyway;MODE=MySQL;DATABASE_TO_LOWER=TRUE
   h2:
     #    開啟console 訪問 默認false
     console:
       enabled: true
       settings:
         #      開啟h2 console 跟蹤 方便調試  默認 false
         trace: true
         #      允許console 遠程訪問 默認false
         web-allow-others: true
       #  h2 訪問路徑上下文
       path: /h2-console

對應Flyway的配置為:

# flyway 配置
spring:
  flyway:
    # 啟用或禁用 flyway
    enabled: true
    # flyway 的 clean 命令會刪除指定 schema 下的所有 table, 生產(chǎn)務必禁掉。這個默認值是 false 理論上作為默認配置是不科學的橙垢。
    clean-disabled: true
    # SQL 腳本的目錄,多個路徑使用逗號分隔 默認值 classpath:db/migration
    locations: classpath:db/migration
    #  metadata 版本控制信息表 默認 flyway_schema_history
    table: flyway_schema_history
    # 如果沒有 flyway_schema_history 這個 metadata 表垛叨, 在執(zhí)行 flyway migrate 命令之前, 必須先執(zhí)行 flyway baseline 命令
    # 設置為 true 后 flyway 將在需要 baseline 的時候, 自動執(zhí)行一次 baseline。
    baseline-on-migrate: true
    # 指定 baseline 的版本號,默認值為 1, 低于該版本號的 SQL 文件, migrate 時會被忽略
    baseline-version: 1
    # 字符編碼 默認 UTF-8
    encoding: UTF-8
    # 是否允許不按順序遷移 開發(fā)建議 true  生產(chǎn)建議 false
    out-of-order: false
    # 需要 flyway 管控的 schema list,這里我們配置為flyway  缺省的話, 使用spring.datasource.url 配置的那個 schema,
    # 可以指定多個schema, 但僅會在第一個schema下建立 metadata 表, 也僅在第一個schema應用migration sql 腳本.
    # 但flyway Clean 命令會依次在這些schema下都執(zhí)行一遍. 所以 確保生產(chǎn) spring.flyway.clean-disabled 為 true
    schemas: flyway
    # 執(zhí)行遷移時是否自動調用驗證   當你的 版本不符合邏輯 比如 你先執(zhí)行了 DML 而沒有 對應的DDL 會拋出異常
    validate-on-migrate: true

請務必仔細閱讀 Flyway 相關配置的說明柜某。

4.3 編寫 SQL 初始化腳本

我們先編寫一個初始化 SQL 文件嗽元,向 H2 數(shù)據(jù)庫已經(jīng)自動初始化的 schema flyway 添加一張 sys_user 表敛纲。請注意命名規(guī)則。腳本名稱為 V1.0.1__Add_table_user.sql 剂癌。SQL 腳本的位置在配置的 spring.flyway.locations 下淤翔。內(nèi)容為:

use `flyway`;
CREATE TABLE `sys_user`
(
    `user_id`         int(10) unsigned NOT NULL AUTO_INCREMENT,
    `username`        varchar(1024)    NOT NULL unique ,
    `encode_password` varchar(1024)       NOT NULL,
    `age`             int(3)           NOT NULL,
    PRIMARY KEY (`user_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

insert into  flyway.sys_user values (1,'Felordcn','{noop}12345',18);

啟動 Spring Boot 應用 。打開 H2 數(shù)據(jù)庫控制臺 http://localhost:8080/h2-console ,在 JDBC URL 一欄粘貼 jdbc:h2:file:D:/h2/flyway;MODE=MySQL;DATABASE_TO_LOWER=TRUE 并點擊 Connect 按鈕會進入以下界面:

這里 -1 是因為我們?nèi)笔×?Flyway 需要的 flyway_schema_history 表 佩谷。0 是因為 H2 數(shù)據(jù)庫自動初始化了 Schema flyway 办铡,其它數(shù)據(jù)庫可能需要你手動來建立。

4.4 編寫 SQL 變更腳本

我們編寫一個 V1.0.0__Delete_sysuser_felordcn.sql 來刪除 V1.0.1__Add_table_user.sql 中初始化的用戶琳要。你會發(fā)現(xiàn)啟動報錯了,因為我們開啟了校驗秤茅,所以對于邏輯錯誤的版本會拋出異常稚补。我們將版本號更改為 V1.0.2__Delete_sysuser_felordcn.sql 再次啟動。通過 H2 數(shù)據(jù)庫控制臺我們會發(fā)現(xiàn)多了一條變更記錄:

同時 sys_user 表的數(shù)據(jù)也沒有了框喳,符合預期课幕。

5. Flyway 最佳實踐

通過上面的介紹相信你很快就會使用 Flyway 進行數(shù)據(jù)庫版本控制了。這里總結了一些在實際開發(fā)中的使用經(jīng)驗:

  1. 生產(chǎn)務必禁 spring.flyway.cleanDisabled=false 五垮。
  2. 盡量避免使用 Undo 模式乍惊。
  3. 開發(fā)版本號盡量根據(jù)團隊來進行多層次的命名避免混亂。比如 V1.0.1__ProjectName_{Feature|fix}_Developer_Description.sql 放仗,這種命名同時也可以獲取更多腳本的開發(fā)者和相關功能的信息润绎。
  4. spring.flyway.outOfOrder 取值 生產(chǎn)上使用 false,開發(fā)中使用 true诞挨。
  5. 多個系統(tǒng)公用一個 數(shù)據(jù)庫 schema 時配置spring.flyway.table 為不同的系統(tǒng)設置不同的 metadata 表名而不使用缺省值 flyway_schema_history 莉撇。

6. 總結

今天我們對 Flyway 數(shù)據(jù)庫版本遷移管理工具進行了介紹并將之與 Spring Boot 相結合。這將大大規(guī)范我們的數(shù)據(jù)庫管理惶傻,提高生產(chǎn)效率棍郎。同時也分享了一些相當有用的生產(chǎn)實踐經(jīng)驗。

** 相關的 DEMO 可通過關注公眾號:Felordcn 回復 flyway 進行獲取银室。**

關注公眾號:碼農(nóng)小胖哥涂佃,獲取更多資訊

個人博客:https://felord.cn

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蜈敢,隨后出現(xiàn)的幾起案子辜荠,更是在濱河造成了極大的恐慌,老刑警劉巖扶认,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侨拦,死亡現(xiàn)場離奇詭異,居然都是意外死亡辐宾,警方通過查閱死者的電腦和手機狱从,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門膨蛮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人季研,你說我怎么就攤上這事敞葛。” “怎么了与涡?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵惹谐,是天一觀的道長。 經(jīng)常有香客問我驼卖,道長氨肌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任酌畜,我火速辦了婚禮怎囚,結果婚禮上,老公的妹妹穿的比我還像新娘桥胞。我一直安慰自己恳守,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布贩虾。 她就那樣靜靜地躺著催烘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缎罢。 梳的紋絲不亂的頭發(fā)上伊群,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音策精,去河邊找鬼在岂。 笑死,一個胖子當著我的面吹牛蛮寂,可吹牛的內(nèi)容都是我干的蔽午。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酬蹋,長吁一口氣:“原來是場噩夢啊……” “哼及老!你這毒婦竟也來了?” 一聲冷哼從身側響起范抓,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤骄恶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匕垫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體僧鲁,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寞秃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斟叼。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖春寿,靈堂內(nèi)的尸體忽然破棺而出朗涩,到底是詐尸還是另有隱情,我是刑警寧澤绑改,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布谢床,位于F島的核電站,受9級特大地震影響厘线,放射性物質發(fā)生泄漏识腿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一造壮、第九天 我趴在偏房一處隱蔽的房頂上張望覆履。 院中可真熱鬧,春花似錦费薄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至析藕,卻和暖如春召廷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背账胧。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工竞慢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人治泥。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓筹煮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親居夹。 傳聞我的和親對象是個殘疾皇子败潦,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355