Go goose
Contents
Goose
数据库版本管理
Goose 是一个用于管理数据库迁移的工具,类似于 Flyway 和 Liquibase。它可以方便地管理数据库模式的版本,并应用相应的 SQL 脚本。你提到在 db/migrations/ 目录下有多个 SQL 文件,这些文件通常是用来管理数据库迁移的。
一、基本使用
1、安装
go install github.com/pressly/goose/v3/cmd/goose@latest
对于不希望安装与数据库连接相关命令的轻量版,可以使用独有的构建标签:
go build -tags='no_postgres no_mysql no_sqlite3 no_ydb' -o goose ./cmd/goose
2、使用方法
以下表格说明了 Goose
工具的基本用法:
命令 | 描述 |
---|---|
up |
将数据库迁移到最新的版本 |
up-to |
迁移到特定版本 |
up-by-one |
从当前版本向上迁移一个版本 |
down |
回滚当前版本的前一个版本 |
down-to |
回滚到特定版本 |
redo |
回滚最新应用的迁移然后重新应用 |
status |
输出当前数据库的迁移状态 |
version |
输出数据库当前的版本 |
create |
创建新的迁移文件,可以选择 sql 或 go 格式 |
fix |
应用序列编号到迁移 |
validate |
检查迁移文件,而不实际运行 |
你可以设置环境变量 GOOSE_DRIVER
, GOOSE_DBSTRING
, 和 GOOSE_MIGRATION_DIR
来定制 Goose
的行为。
Goose支持的数据库类型
mssql
,sqlserver
,mysql
,tidb
,sqlite3
,clickhouse
等
具体看 goose.OpenDBWithDriver()
方法
二、集成
package main
import (
"context"
"flag"
"log"
"os"
"github.com/pressly/goose/v3"
_ "modernc.org/sqlite"
)
var (
flags = flag.NewFlagSet("goose", flag.ExitOnError)
dir = flags.String("dir", ".", "directory with migration files")
)
func main() {
flags.Parse(os.Args[1:])
args := flags.Args()
if len(args) < 3 {
flags.Usage()
return
}
dbstring, command := args[1], args[2]
db, err := goose.OpenDBWithDriver("sqlite", dbstring)
if err != nil {
log.Fatalf("goose: failed to open DB: %v\n", err)
}
defer func() {
if err := db.Close(); err != nil {
log.Fatalf("goose: failed to close DB: %v\n", err)
}
}()
arguments := []string{}
if len(args) > 3 {
arguments = append(arguments, args[3:]...)
}
if err := goose.RunContext(context.Background(), command, db, *dir, arguments...); err != nil {
log.Fatalf("goose %v: %v", command, err)
}
}
使用
[root@Sugar goose]🐳 ./cccs sqlite3 ./foo.db status
2024/11/24 15:28:17 goose status: failed to collect migrations: no migration files found
[root@Sugar goose]🐳 ./cccs sqlite3 ./foo.db status -dir dbFile
2024/11/24 15:28:32 goose status: failed to collect migrations: no migration files found
[root@Sugar goose]🐳 ./cccs -dir dbFile sqlite3 ./foo.db status
2024/11/24 15:28:51 Applied At Migration
2024/11/24 15:28:51 =======================================
2024/11/24 15:28:51 Pending -- 20241124142616_v24_2_1_add_some_column.sql
[root@Sugar goose]🐳 ./cccs -dir dbFile sqlite3 ./foo.db up
2024/11/24 15:29:05 OK 202411xxxx2616_v24_2_1_add_some_column.sql (2.57ms)
2024/11/24 15:29:05 goose: successfully migrated database to version: 20241124142616
[root@Sugar goose]🐳 ./cccs -dir dbFile sqlite3 ./foo.db down
2024/11/24 15:31:04 OK 20241124142616_v24_2_1_add_some_column.sql (2.96ms)
[root@Sugar goose]🐳 ./cccs -dir dbFile sqlite3 ./foo.db up
2024/11/24 15:32:08 OK 20241124142616_v24_2_1_add_some_column.sql (2.77ms)
2024/11/24 15:32:08 goose: successfully migrated database to version: 20241124142616
[root@Sugar goose]🐳
sql 文件打包到二进制中
//go:embed docs/sql/*.sql
var Migrations embed.FS
func GenTable(migrations embed.FS, gooseArgs []string, dir string) {
goose.SetBaseFS(migrations)
command := gooseArgs[0]
gooseDB, err := goose.OpenDBWithDriver(config.Cfg.Database.Type, config.Cfg.Database.DBname)
if err != nil {
slog.Error("goose: failed to open DB", "err", err)
}
defer func() {
if err := gooseDB.Close(); err != nil {
slog.Error("goose: failed to close DB", "err", err)
}
}()
arguments := []string{}
if len(gooseArgs) > 1 {
arguments = append(arguments, gooseArgs[1:]...)
}
if err := goose.RunContext(context.Background(), command, gooseDB, dir, arguments...); err != nil {
slog.Error("goose: failed to run cmd", "cmd", command, "err", err)
}
}