1.引言
想到要管理數據庫的版本,是在實際產品中遇到問題后想到的一種解決方案,當時各個環境的數據庫亂作一團,沒有任何一個人(開發、測試、維護人員)能夠講清楚當前環境下的數據庫是哪個版本,與哪個版本的應用相匹配,如何升級到與新版本的應用相匹配。
想到管理數據庫版本時,先是心底形成了一個初步的解決方案,大致是通過數據庫中的某張表來記錄數據庫表結構的歷次更新與對應版本,在每次數據庫表結構調整時除了提供庫表更新sql ,還必須提供更新記錄與對應版本的sql,以幫助維護數據庫版本信息,並在遇到問題時提供相關的排查依據。
后來據此思路在網絡上搜索了一把,結果搜到Liquibase (另一款開源數據庫版本管理工具)。在學習了解Liquibase 的時候,經高手介紹又了解到了Flyway 這個項目的存在。經過一番了解,最后我們選擇了Flyway ,主要原因是Flyway 支持sql 腳本,而Liquibase 只支持XML 方式的數據庫表結構定義,雖然在新的版本中號稱在XML的數據庫表結構定義方式中支持了sql 腳本。
雖然Flyway 的中文文檔近乎為零,英文文檔也鳳毛麟角,但它卻是我們最理想的數據庫版本管理工具,它不但支持sql 腳本,還支持Java 代碼直接操作數據庫(在版本升級時做數據遷移相當有用),有Maven 插件,支持命令行(我們的平台數據庫有部分由C 語言項目管理),而且在Spring 框架的配合下,很容易就能實現應用啟動時自動檢查並升級數據庫的功能。
2.什么是flyway
Flyway 是獨立於數據庫的應用、管理並跟蹤數據庫變更的數據庫版本管理工具。
Flyway 的項目主頁是 http://flywaydb.org/ )(最近才遷移到這個主頁,之前一直在googlecode 下管理http://code.google.com/p/flyway/ ),在項目的主頁上可以看到Flyway 與幾款主流數據庫版本管理工具的特性對比列表。
3.為什么使用flyway
我們遇到的問題(以下內容來自Flyway 的一些英文文檔,從中抽取出來的我們也遇到的一些主要問題):
- 不同的開發人員在開發產品特性時,都有可能更新數據庫(添加新表,新的約束等)。當開發人員完成工作並提交代碼時,代碼會被合並到主分支並在測試服務器上執行單元測試與集成測試。我們在哪個環節來執行數據庫的更新操作呢?由QA 部門手工執行sql 腳本?或者我們開發一斷程序自動執行數據庫更新?以什么順序來執行這些更新腳本?這些問題同樣存在於生產環境。
- 我們的產品部署在不同的客戶服務器上,以及很多的測試、聯調、實驗局、銷售環境上。不同的客戶和測試環境上都部署着不同版本的產品。當他們需要升級他們的產品到新的版本時,我們不僅需要讓他們的管理員可以升級產品到新的版本,同時需要保留他們的已有數據。在升級產品的步驟中,我們清楚地知道客戶數據庫的當前版本,以及需要在該數據庫上執行哪些數據庫更新腳本,來更新數據庫表結構與數據庫中已存在的數據。當升級完成時,數據庫表結構及數據應當與升級后的產品版本保持一致。
- 有的時候,我們需要通過代碼(Java )來維護一些已存在的數據,如通過代碼來維護blob 類型的用戶頭像數據。
- 當升級失敗時(比如在升級過程中出現網絡連接失敗),我們應當支持對失敗進行修復。
4.如何使用flyway
Flyway 的主要任務是管理數據庫的版本更新,在Flyway 中稱每次數據庫更新為一個migration ,為了更順口,我們下面稱之為數據庫腳本。Flyway 支持SQL-based migrations 和Java-based migrations 。
Flyway 支持的數據庫腳本有sql 腳本與java 代碼,sql 腳本即普通的sql 腳本,包含創建數據庫、表,更新庫表結構,數據插入、更新、刪除等sql 語句,java 代碼則是通過一個有效的數據源,使用java 語言來進行數據庫的操作,這里針對的讀者是對數據庫操作有一定熟悉程度的群體,不再詳細講解如何編寫數據庫腳本。
- SQL 腳本文件默認位置是項目的源文件夾下的db/migration 目錄。
- Java 代碼默認位於db.migration 包。
- SQL 腳本文件及Java 代碼類名必須遵循以下命名規則:V<version>[_<SEQ>][__description] 。版本號的數字間以小數點(. )或下划線(_ )分隔開,版本號與描述間以連續的兩個下划線(__ )分隔開。如V1_1_0__Update.sql 。Java 類名規約不允許存在小數點,所以Java 類名中版本號的數字間只能以下划線進行分隔。
- 創建maven環境
![]()
- 增加flyway依賴
<dependency> <groupId>com.googlecode.flyway</groupId> <artifactId>flyway-core</artifactId> <version>2.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency>- 整合flyway
Flyway flyway = new Flyway(); flyway.setInitOnMigrate(true);//Whether to automatically call init when migrate is executed against a non-empty schema with no metadata table. flyway.setInitVersion("0");//設置初始化版本 flyway.setDataSource(dataSource); flyway.setTable(databaseMigrateInfo.getTable());//設置存放flyway metadata數據的表名 flyway.setLocations(new String[] { databaseMigrateInfo .getLocation() });//設置flyway掃描sql升級腳本、java升級腳本的目錄路徑或包路徑 flyway.migrate();注意:1.會生成版本管理表;
2.版本號可以從0開始,可以設置初始化版本;