flyway是什么?
Flyway是一個(gè)簡(jiǎn)單開(kāi)源數(shù)據(jù)庫(kù)版本控制器(約定大于配置),主要提供migrate、clean、info、validate、baseline、repair等命令。它支持SQL(PL/SQL、T-SQL)方式和Java方式,支持命令行客戶端等,還提供一系列的插件支持(Maven、Gradle、SBT、ANT等)。
Flyway是獨(dú)立于數(shù)據(jù)庫(kù)的應(yīng)用、管理并跟蹤數(shù)據(jù)庫(kù)變更的數(shù)據(jù)庫(kù)版本管理工具。用通俗的話講,F(xiàn)lyway可以像Git管理不同人的代碼那樣,管理不同人的sql腳本,從而做到數(shù)據(jù)庫(kù)同步。
注意:
flyway在執(zhí)行腳本時(shí),會(huì)在源數(shù)據(jù)表中檢查checksum值,并確定上次運(yùn)行到哪一個(gè)腳本文件,本次執(zhí)行時(shí)從下一條腳本文件開(kāi)始執(zhí)行。所以編寫腳本的時(shí)候不要去修改原有的腳本內(nèi)容,并且新的腳本版本號(hào)要連續(xù)
為什么要使用flyway
通常在項(xiàng)目開(kāi)始時(shí)會(huì)針對(duì)數(shù)據(jù)庫(kù)進(jìn)行全局設(shè)計(jì),但在開(kāi)發(fā)產(chǎn)品新特性過(guò)程中,難免會(huì)遇到需要更新數(shù)據(jù)庫(kù)Schema的情況,比如:添加新表,添加新字段和約束等,這種情況在實(shí)際項(xiàng)目中也經(jīng)常發(fā)生。那么,當(dāng)開(kāi)發(fā)人員完成了對(duì)數(shù)據(jù)庫(kù)更的SQL腳本后,如何快速地在其他開(kāi)發(fā)者機(jī)器上同步?并且如何在測(cè)試服務(wù)器上快速同步?以及如何保證集成測(cè)試能夠順利執(zhí)行并通過(guò)呢?
在日常的開(kāi)發(fā)中,我們使用git管理代碼的版本,那么數(shù)據(jù)庫(kù)的版本呢?使用flyway。
個(gè)人認(rèn)為,可以大概的將flyway理解為數(shù)據(jù)庫(kù)的git,方便多人協(xié)作及記錄。
git:讓你和同事更加輕松的維護(hù)同一個(gè)項(xiàng)目,你可以很方便的獲取到他最新提交的改動(dòng)。
flyway:讓你及時(shí)的知道同事對(duì)數(shù)據(jù)庫(kù)的改動(dòng)并且能夠自動(dòng)在你的本地執(zhí)行這些改動(dòng)。
解決的問(wèn)題
和同事同時(shí)維護(hù)一個(gè)項(xiàng)目,同時(shí)對(duì)數(shù)據(jù)庫(kù)做出了一些修改,我在使用git拉取了最新的代碼之后,運(yùn)行總是報(bào)錯(cuò),需要自己去重新執(zhí)行一遍該表的創(chuàng)建語(yǔ)句來(lái)在本地進(jìn)行創(chuàng)建,使用flyway后,拉取最新代碼的同時(shí)會(huì)拉取最新的sql文件,同時(shí)在服務(wù)啟動(dòng)時(shí)自動(dòng)創(chuàng)建數(shù)據(jù)表,對(duì)一些和自己無(wú)關(guān)的數(shù)據(jù)表完全不用關(guān)心了。
新接手一個(gè)項(xiàng)目,在本地進(jìn)行開(kāi)發(fā)調(diào)試,本地新建數(shù)據(jù)庫(kù)后,需要執(zhí)行一遍建表語(yǔ)句,使用flyway可以自動(dòng)的創(chuàng)建該項(xiàng)目的所有表格。
其他相似工具
- 數(shù)據(jù)庫(kù)遷移工具
github.com/golang-migrate/migrate
- git類型的數(shù)據(jù)庫(kù)dolt
github.com/liquidata-inc/dolt // 線上關(guān)系型數(shù)據(jù)庫(kù)
(不適合) goway
使用方法:
https://blog.csdn.net/poem_2010/article/details/86241999
https://blog.csdn.net/weixin_39827798/article/details/111865637
安裝對(duì)應(yīng)的go庫(kù)
go get github.com/poemp/goway // 使用的人很少
配置
需要參數(shù)配置
type WayConfigure struct {
Host string
Port string
User string
Password string
DbName string
SearchPath string // 數(shù)據(jù)庫(kù)
Table string // 版本記錄表名
Path string // 存放地址
}
首先需要做配置, 請(qǐng)?jiān)趩?dòng)的時(shí)候重寫
inter.DefaultTableDataSource = func() inter.WayConfigure {
return inter.WayConfigure{
Host: host,
Port: port,
User: user,
Password: password,
DbName: dbName,
SearchPath: searchPath,
Table: table,
Path: path,
}
}
然后, 調(diào)用手動(dòng)執(zhí)行
way.Flyway{}.Execu()
package main
import (
"fmt"
"github.com/jinzhu/gorm"
"github.com/lunny/log"
"github.com/poemp/goway/inter"
"github.com/poemp/goway/way"
)
func main() {
GetWayBD()
}
// GetWayBD 獲取數(shù)據(jù)庫(kù)連接
func GetWayBD() *gorm.DB {
// 關(guān)閉
defer func() {
if e := recover(); e != nil {
fmt.Println(fmt.Sprintf("recover from a fatal error : %v", e))
}
}()
inter.DefaultTableDataSource = func() inter.WayConfigure {
return inter.WayConfigure{
Host: "127.0.0.1",
Port: "9999",
User: "root",
Password: "123456",
DbName: "WorkStream",
SearchPath: "searchPath",
Table: "table",
Path: "path",
}
}
way.Flyway{}.Execu()
c := inter.DefaultTableDataSource()
source := fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=%s password=%s",
c.Host, c.Port, c.User, c.DbName, "disable", c.Password)
log.Info("way datasource :" + source)
// 支持其他的數(shù)據(jù)庫(kù), 需要修改這兒, 并且需要在代碼中添加 其他數(shù)據(jù)庫(kù)的驅(qū)動(dòng)
// 就像我使用的 post 數(shù)據(jù)庫(kù) 是需要在import中加入:
// _ "github.com/jinzhu/gorm/dialects/postgres"
db, err := gorm.Open("postgres", source)
db.SingularTable(true)
db.LogMode(true)
if err != nil {
panic(err)
}
return db
}
踩坑點(diǎn)
需要修改 github.com/poemp/goway 里的db_config.go 依賴
github.com/go-xorm/core ---> xorm.io/core

(適合) golang-migrate
基本使用案例
Go migrate文檔: https://pkg.go.dev/github.com/golang-migrate/migrate#New
簡(jiǎn)單的使用案例
cmd使用
https://github.com/golang-migrate/migrate/tree/master/cmd/migrate
Windows下載地址
https://github.com/golang-migrate/migrate/releases/download/v4.15.1/migrate.windows-amd64.zip
注: 下載完畢之后將里面的migrate.exe文件復(fù)制到咱們想要執(zhí)行的目錄下即可
Linux下載地址
https://github.com/golang-migrate/migrate/releases/download/v4.15.1/migrate.linux-arm64.tar.gz
golang-migrate使用
package main
import (
"database/sql"
"fmt"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/mysql"
_ "github.com/golang-migrate/migrate/v4/source/file"
"log"
)
func main() {
// 連接數(shù)據(jù)庫(kù)
db, _ := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/workstream")
if err := db.Ping(); err != nil {
log.Fatalf("could not ping DB... %v", err)
}
// 開(kāi)始遷移
driver, _ := mysql.WithInstance(db, &mysql.Config{})
m, err := migrate.NewWithDatabaseInstance(
fmt.Sprintf("file://%s", "./migrations"), // file://path/to/directory
"mysql", driver)
if err != nil {
log.Fatalf("migration failed... %v", err)
}
// 執(zhí)行操作: up --> 更新, down --> 回滾
if err = m.Up(); err != nil && err != migrate.ErrNoChange {
fmt.Printf("An error occurred while syncing the database.. %v", err)
}
}
參考文章:
(重點(diǎn): 函數(shù)的使用方法)https://blog.csdn.net/Matthew__M/article/details/123427027
(重點(diǎn): migrate在gin中的應(yīng)用)https://blog.csdn.net/weixin_26737625/article/details/108494299
(重點(diǎn): migrate cli 實(shí)踐)https://a2htray.github.io/2021/02/06/golang-migrate-usage-with-postgresql/
(重點(diǎn): go migrate 測(cè)試)https://blog.csdn.net/doyzfly/article/details/121096806
(重點(diǎn): go migrate 簡(jiǎn)單應(yīng)用)https://www.cnblogs.com/super-egg/p/15080547.html
(重點(diǎn)) 項(xiàng)目中的使用
命令行用法
// 命令案例: 查看當(dāng)前數(shù)據(jù)庫(kù)版本
migrate -database mysql://root:123456@tcp(127.0.0.1:3306)/workstream -path . version
// 在當(dāng)前migration文件夾里插入一個(gè)兩個(gè)表(up, down)
migrate -database mysql://root:123456@tcp(127.0.0.1:3306)/workstream -path . create -ext sql -dir . -seq alter_users_column
------------------------------------------------------------------------------------------------------
Usage: migrate OPTIONS COMMAND [arg...]
migrate [ -version | -help ]
Options:
-source 遷移的位置 (driver://url)
-path sql腳本位置 -source=file://path
-database 對(duì)此數(shù)據(jù)庫(kù)運(yùn)行遷移 (driver://url)
-prefetch N 在執(zhí)行之前要提前加載的遷移數(shù) (default 10)
-lock-timeout N 允許 N 秒獲取數(shù)據(jù)庫(kù)鎖定 (default 15)
-verbose 打印詳細(xì)日志記錄
-version 打印 migrate 版本
-help 打印用法
Commands:
create [-ext E] [-dir D] [-seq] [-digits N] [-format] [-tz] NAME
Create a set of timestamped up/down migrations titled NAME, in directory D with extension E.
Use -seq 生成 N 位數(shù)字的順序上/下遷移。
Use -format 指定 Go 時(shí)間格式字符串。注意:具有相同時(shí)間的遷移會(huì)導(dǎo)致"重復(fù)遷移版本"錯(cuò)誤。
Use -tz 指定生成非順序遷移時(shí)將使用的時(shí)區(qū)(默認(rèn)值:UTC)
goto V 遷移到第 V 個(gè)數(shù)據(jù)庫(kù)版本
up [N] 應(yīng)用所有或 N 個(gè)向上遷移
down [N] [-all] 應(yīng)用所有或 N 個(gè)向下遷移
drop [-f] (強(qiáng)制) 刪除所有數(shù)據(jù)庫(kù)中的數(shù)據(jù)
force V 設(shè)置版本 V 但不運(yùn)行遷移(忽略臟狀態(tài))
version 打印當(dāng)前遷移版本
Goland DDL映射
使用步驟
最終目的: 一句話概括, 將我們本地的sql腳本和遠(yuǎn)程數(shù)據(jù)庫(kù)連接上! ! !




缺點(diǎn):
只能映射sql腳本創(chuàng)建表的語(yǔ)句, 其他修改列字段相關(guān)的操作不支持, 且同步的時(shí)候會(huì)多出現(xiàn)一些key, 容易操作失誤, 且版本回退沒(méi)有清晰地表示, 只有相應(yīng)時(shí)間點(diǎn)的改動(dòng), 不太專業(yè).
項(xiàng)目場(chǎng)景
當(dāng)線上數(shù)據(jù)庫(kù)存在數(shù)據(jù), 且需要后續(xù)添加, 修改, 刪除字段
線上數(shù)據(jù)庫(kù)能否回退版本并且有清晰地版本號(hào), 令開(kāi)發(fā)者一目了然
支持多人團(tuán)隊(duì)協(xié)作開(kāi)發(fā), 且功能全面
后面更新項(xiàng)目場(chǎng)景的解決問(wèn)題......