資料庫版本管理工具Flyway應用

aoho發表於2018-08-15

Flyway介紹

Flyway是一款開源的資料庫版本管理工具,它更傾向於規約優於配置的方式。Flyway可以獨立於應用實現管理並跟蹤資料庫變更,支援資料庫版本自動升級,並且有一套預設的規約,不需要複雜的配置,Migrations可以寫成SQL指令碼,也可以寫在Java程式碼中,不僅支援Command Line和Java API,還支援Build構建工具和Spring Boot等,同時在分散式環境下能夠安全可靠地升級資料庫,同時也支援失敗恢復等。

Flyway用途

通常在專案開始時會針對資料庫進行全域性設計,但在開發產品新特性過程中,難免會遇到需要更新資料庫Schema的情況,比如:新增新表,新增新欄位和約束等,這種情況在實際專案中也經常發生。那麼,當開發人員完成了對資料庫更的SQL指令碼後,如何快速地在其他開發者機器上同步?並且如何在測試伺服器上快速同步?以及如何保證整合測試能夠順利執行並通過呢?

到各測試伺服器上手動執行SQL指令碼費時費神費力的,幹嘛不自動化呢,當然,對於高階別和PROD環境,還是需要DBA手動執行的。最後,寫一段自動化程式來自動執行更新,想法是很好的,那如果已經有了一些外掛或庫可以幫助你更好地實現這樣的功能,為何不好好利用一下呢,當然,如果是為了學習目的,重複造輪子是無可厚非的。其實,以上可以通過Flyway工具來解決,Flyway可以實現自動化的資料庫版本管理,並且能夠記錄資料庫版本更新記錄。

Flyway命令

Flyway對資料庫進行版本管理主要由Metadata表和6種命令完成,Metadata主要用於記錄後設資料,每種命令功能和解決的問題範圍不一樣,以下分別對metadata表和這些命令進行闡述,其中的示意圖都來自Flyway的官方文件。

Metadata Table

Flyway中最核心的就是用於記錄所有版本演化和狀態的Metadata表,在Flyway首次啟動時會建立預設名為flyway_schema_history的後設資料表,其表結構為(以MySQL為例):

資料庫版本管理工具Flyway應用

Migrate

Migrate是指把資料庫Schema遷移到最新版本,是Flyway工作流的核心功能,Flyway在Migrate時會檢查Metadata(後設資料)表,如果不存在會建立Metadata表,Metadata表主要用於記錄版本變更歷史以及Checksum之類的。

資料庫版本管理工具Flyway應用

Migrate時會掃描指定檔案系統或Classpath下的Migrations(可以理解為資料庫的版本指令碼),並且會逐一比對Metadata表中的已存在的版本記錄,如果有未應用的Migrations,Flyway會獲取這些Migrations並按次序Apply到資料庫中,否則不需要做任何事情。另外,通常在應用程式啟動時應預設執行Migrate操作,從而避免程式和資料庫的不一致性。

Clean

清除掉對應資料庫Schema中的所有物件,包括表結構,檢視,儲存過程,函式以及所有的資料等都會被清除。Clean操作在開發和測試階段是非常有用的,它能夠幫助快速有效地更新和重新生成資料庫表結構,但特別注意的是:不應在Production的資料庫上使用!

Info

Info用於列印所有Migrations的詳細和狀態資訊,其實也是通過Metadata表和Migrations完成的,下圖很好地示意了Info列印出來的資訊。Info能夠幫助快速定位當前的資料庫版本,以及檢視執行成功和失敗的Migrations。

資料庫版本管理工具Flyway應用

Validate

Validate是指驗證已經Apply的Migrations是否有變更,Flyway是預設是開啟驗證的。Validate原理是對比Metadata表與本地Migrations的Checksum值,如果值相同則驗證通過,否則驗證失敗,從而可以防止對已經Apply到資料庫的本地Migrations的無意修改。

Baseline

Baseline針對已經存在Schema結構的資料庫的一種解決方案,即實現在非空資料庫中新建Metadata表,並把Migrations應用到該資料庫。Baseline可以應用到特定的版本,這樣在已有表結構的資料庫中也可以實現新增Metadata表,從而利用Flyway進行新Migrations的管理了。

Repair

Repair操作能夠修復Metadata表,該操作在Metadata表出現錯誤時是非常有用的。Repair會修復Metadata表的錯誤,通常有兩種用途:

  • 移除失敗的Migration記錄,該問題只是針對不支援DDL事務的資料庫。
  • 重新調整已經應用的Migratons的Checksums值,比如:某個Migratinon已經被應用,但本地進行了修改,又期望重新應用並調整Checksum值,不過儘量不要這樣操作,否則可能造成其它環境失敗。

支援的資料庫

目前Flyway支援的資料庫還是挺多的,包括:Oracle, SQL Server, SQL Azure, DB2, DB2 z/OS, MySQL(including Amazon RDS), MariaDB, Google Cloud SQL, PostgreSQL(including Amazon RDS and Heroku), Redshift, Vertica, H2, Hsql, Derby, SQLite, SAP HANA, solidDB, Sybase ASE and Phoenix。

Flyway應用

Flyway可以通過命令列和外掛(如maven)的方式執行相應的命令,具體可以參考https://flywaydb.org/getstarted/firststeps/commandline

本文將會重點講解在Spring Boot中應用Flyway。

引入依賴

<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
	<groupId>org.flywaydb</groupId>
	<artifactId>flyway-core</artifactId>
	<version>5.0.7</version>
</dependency>
複製程式碼

配置Flyway

flyway:
  locations: classpath:db/migration
  baseline-on-migrate: true
  url: jdbc:mysql://localhost:3306/test
  sql-migration-prefix: V
  sql-migration-suffix: .sql
複製程式碼

我們在配置檔案中指定了如上的屬性。Flyway的配置屬性意義如下:

  • flyway.baseline-version:執行基線時用來標記已有Schema的版本(預設值:1)
  • flyway.enabled:開啟Flyway (預設為true)
  • flyway.sql-migration-prefix:SQL遷移的檔名字首
  • flyway.sql-migration-suffix :SQL遷移的檔名字尾
  • flyway.baseline-on-migrate:在沒有後設資料表的情況下,針對非空Schema執行遷移時是否自動呼叫基線
  • flyway.location:遷移指令碼的位置(預設為db/migration)

正確建立Migrations

Migrations是指Flyway在更新資料庫時是使用的版本指令碼,比如:一個基於Sql的Migration命名為V1__init_tables.sql,內容即是建立所有表的sql語句,另外,Flyway也支援基於Java的Migration。Flyway載入Migrations的預設Locations為classpath:db/migration,也可以指定filesystem:/project/folder,其載入是在Runtime自動遞迴地執行的。

除了需要指定Location外,Flyway對Migrations的掃描還必須遵從一定的命名模式,Migration主要分為兩類:Versioned和Repeatable。

  • Versioned migrations
    一般常用的是Versioned型別,用於版本升級,每一個版本都有一個唯一的標識並且只能被應用一次,並且不能再修改已經載入過的Migrations,因為Metadata表會記錄其Checksum值。其中的version標識版本號,由一個或多個數字構成,數字之間的分隔符可以採用點或下劃線,在執行時下劃線其實也是被替換成點了,每一部分的前導零會被自動忽略。

  • Repeatable migrations
    Repeatable是指可重複載入的Migrations,其每一次的更新會影響Checksum值,然後都會被重新載入,並不用於版本升級。對於管理不穩定的資料庫物件的更新時非常有用。Repeatable的Migrations總是在Versioned之後按順序執行,但開發者必須自己維護指令碼並且確保可以重複執行,通常會在sql語句中使用CREATE OR REPLACE來保證可重複執行。

資料庫版本管理工具Flyway應用

其中的檔名由以下部分組成,除了使用預設配置外,某些部分還可自定義規則。

  • prefix: 可配置,字首標識,預設值V表示Versioned,R表示Repeatable
  • version: 標識版本號,由一個或多個數字構成,數字之間的分隔符可用點.或下劃線_
  • separator: 可配置,用於分隔版本標識與描述資訊,預設為兩個下劃線__
  • description: 描述資訊,文字之間可以用下劃線或空格分隔
  • suffix: 可配置,後續標識,預設為.sql

資料庫版本管理工具Flyway應用

建立sql指令碼檔案

資料庫版本管理工具Flyway應用

如上所示即為我們在服務中建立的sql指令碼,啟動服務之後會看到如下的日誌資訊:

資料庫版本管理工具Flyway應用

說明當前資料庫指令碼是最新的,schema_version表中最新的版本為1.4。

總結

本文主要介紹了Flyway,包括其提供的6中命令和如何使用Flyway。Flyway可以有效改善資料庫版本管理方式,通常在local和dev環境中簡化了很多不必要的繁瑣操作,當然在產線上應用Flyway需要非常慎重,可能會對線上的資料造成非常嚴重的後果。

訂閱最新文章,歡迎關注我的公眾號

微信公眾號

參考

  1. Flyway
  2. 快速掌握和使用Flyway

相關文章