假如我們有一個(gè)叫shiny的項(xiàng)目,它是由一個(gè)程序Shiny-Server 和一個(gè)數(shù)據(jù)庫(kù) Shiny-DB組成的;
簡(jiǎn)單結(jié)構(gòu)圖如下:

但是很多時(shí)候,現(xiàn)實(shí)開(kāi)發(fā)團(tuán)隊(duì)是這樣的:

我們的項(xiàng)目shiny項(xiàng)目的運(yùn)行環(huán)境是有多套的,
我們擅長(zhǎng)解決代碼層面的問(wèn)題。
版本控制工具git非常普遍而且好用
我們有持續(xù)集成和持續(xù)構(gòu)建的工具
我們很好的定義了測(cè)試和生產(chǎn)環(huán)境的發(fā)布流程

但是我們的數(shù)據(jù)庫(kù)的版本如何控制呢?

當(dāng)前現(xiàn)狀
非常不幸的是我們還不能很好的處理數(shù)據(jù)庫(kù)的版本管理問(wèn)題,
很多的項(xiàng)目依賴運(yùn)維人員手動(dòng)的執(zhí)行SQL腳本,
有的時(shí)候甚至為了快速解決bug去快速的在命令行上執(zhí)行SQL腳本,那么問(wèn)題來(lái)了。

通常這些問(wèn)題的答案是:鬼知道。
引入目的
flyway解決了上面的這些問(wèn)題。

目前Flyway支持的數(shù)據(jù)庫(kù)還是挺多的,包括:
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的執(zhí)行流程
Flyway是一款開(kāi)源的數(shù)據(jù)庫(kù)版本管理工具,
它更傾向于規(guī)約優(yōu)于配置的方式。
Flyway可以獨(dú)立于應(yīng)用實(shí)現(xiàn)管理并跟蹤數(shù)據(jù)庫(kù)變更,支持?jǐn)?shù)據(jù)庫(kù)版本自動(dòng)升級(jí),
并且有一套默認(rèn)的規(guī)約,不需要復(fù)雜的配置,
Migrations可以寫成SQL腳本,也可以寫在Java代碼中,
不僅支持Command Line和Java API,還支持Build構(gòu)建工具和Spring Boot等,
同時(shí)在分布式環(huán)境下能夠安全可靠地升級(jí)數(shù)據(jù)庫(kù),同時(shí)也支持失敗恢復(fù)等。

每次不管是數(shù)據(jù)庫(kù)的表結(jié)構(gòu)或者表數(shù)據(jù)的變更,
你只需要把問(wèn)題當(dāng)成一次數(shù)據(jù)庫(kù)的升級(jí),
簡(jiǎn)單的創(chuàng)建一個(gè)比當(dāng)前版本更高的版本的遷移SQL文件或者Java文件,
下次Flyway啟動(dòng)的時(shí)候,他會(huì)找到這些腳本并把它更新到數(shù)據(jù)庫(kù)。
腳本或者Java遷移腳本的命名規(guī)則:
其中的文件名由以下部分組成,除了使用默認(rèn)配置外,某些部分還可自定義規(guī)則。
- prefix: 可配置,前綴標(biāo)識(shí),默認(rèn)值
V表示Versioned,R表示Repeatable - version: 標(biāo)識(shí)版本號(hào),由一個(gè)或多個(gè)數(shù)字構(gòu)成,數(shù)字之間的分隔符可用點(diǎn)
.或下劃線_ - separator: 可配置,用于分隔版本標(biāo)識(shí)與描述信息,默認(rèn)為兩個(gè)下劃線
__ - description: 描述信息,文字之間可以用下劃線或空格分隔
- suffix: 可配置,后續(xù)標(biāo)識(shí),默認(rèn)為
.sql
實(shí)現(xiàn)路徑

真實(shí)項(xiàng)目版本更新場(chǎng)景中,我們不可能再基于人力去做這件事情,我們選擇的是API的方式。
使用步驟如下:

一般大家都是寫SQL腳本,也支持通過(guò)寫Java代碼的方式來(lái)實(shí)現(xiàn)。
Java方式寫遷移功能

使用步驟:

目前的集成方式
使用的是springboot的方式集成了Flyway;

配置參數(shù):可自行翻譯和參考選擇去配置
flyway.baseline-description= # The description to tag an existing schema with when executing baseline.
flyway.baseline-version=1 # Version to start migration.
flyway.baseline-on-migrate=false # Whether to execute migration against a non-empty schema with no metadata table
flyway.check-location=false # Check that migration scripts location exists.
flyway.clean-on-validation-error=false # will clean all objects. Warning! Do NOT enable in production!
flyway.enabled=true # Enable flyway.
flyway.encoding=UTF-8 # The encoding of migrations.
flyway.ignore-failed-future-migration=true # Ignore future migrations when reading the metadata table.
flyway.init-sqls= # SQL statements to execute to initialize a connection immediately after obtaining it.
flyway.locations=classpath:db/migration # locations of migrations scripts.
flyway.out-of-order=false # Allows migrations to be run "out of order".
flyway.placeholder-prefix= # The prefix of every placeholder.
flyway.placeholder-replacement=true # Whether placeholders should be replaced.
flyway.placeholder-suffix=} # The suffix of every placeholder.
flyway.placeholders.*= # Placeholders to replace in Sql migrations.
flyway.schemas= # Default schema of the connection and updating
flyway.sql-migration-prefix=V # The file name prefix for Sql migrations
flyway.sql-migration-separator=__ # The file name separator for Sql migrations
flyway.sql-migration-suffix=.sql # The file name suffix for Sql migrations
flyway.table=schema_version # The name of Flyway's metadata table.
flyway.url= # JDBC url of the database to migrate. If not set, the primary configured data source is used.
flyway.user= # Login user of the database to migrate. If not set, use spring.datasource.username value.
flyway.password= # JDBC password if you want Flyway to create its own DataSource.
flyway.validate-on-migrate=true # Validate sql migration CRC32 checksum in classpath.
package db.migration;
/**
* @author carter
* create_date 2020/8/13 17:39
* description java數(shù)據(jù)庫(kù)變更模板代碼
*/
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import java.sql.ResultSet;
import java.sql.Statement;
@Slf4j
public class V2__test extends BaseJavaMigration {
@Override
public void migrate(Context context) throws Exception {
try (Statement select = context.getConnection().createStatement()) {
try (ResultSet rows = select.executeQuery("SELECT 1")) {
while (rows.next()) {
int id = rows.getInt(1);
String anonymizedName = "Anonymous" + id;
log.info("執(zhí)行sql腳本:{}",anonymizedName);
}
}
}
}
}
資料來(lái)源
官網(wǎng): https://flywaydb.org/
實(shí)戰(zhàn): https://blog.waterstrong.me/flyway-in-practice/
如有問(wèn)題,請(qǐng)留言。
原創(chuàng)不易,關(guān)注誠(chéng)可貴,轉(zhuǎn)發(fā)價(jià)更高!轉(zhuǎn)載請(qǐng)注明出處,讓我們互通有無(wú),共同進(jìn)步,歡迎溝通交流。
我會(huì)持續(xù)分享Java軟件編程知識(shí)和程序員發(fā)展職業(yè)之路,歡迎關(guān)注!

