golang数据库迁移工具插件sql-migrate支持嵌入式迁移文件的使用

Golang数据库迁移工具插件sql-migrate支持嵌入式迁移文件的使用

sql-migrate是一个基于gorp和goose的Go语言SQL模式迁移工具,它支持将迁移文件嵌入到应用程序中。

嵌入式迁移文件的使用方法

使用embed包嵌入迁移文件

  1. 首先在项目中创建迁移文件,例如在migrations/目录下创建SQL文件
  2. 使用Go 1.16+的embed功能嵌入这些文件:
import "embed"

//go:embed migrations/*
var dbMigrations embed.FS
  1. 创建迁移源:
migrations := migrate.EmbedFileSystemMigrationSource{
    FileSystem: dbMigrations,
    Root:       "migrations",
}

完整示例

package main

import (
    "database/sql"
    "embed"
    "fmt"
    "log"
    
    "github.com/rubenv/sql-migrate"
    _ "github.com/mattn/go-sqlite3"
)

//go:embed migrations/*.sql
var migrationFS embed.FS

func main() {
    // 打开数据库连接
    db, err := sql.Open("sqlite3", "test.db")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 设置迁移源
    migrations := &migrate.EmbedFileSystemMigrationSource{
        FileSystem: migrationFS,
        Root:       "migrations",
    }
    
    // 执行迁移
    n, err := migrate.Exec(db, "sqlite3", migrations, migrate.Up)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("成功应用了%d个迁移!\n", n)
}

迁移文件示例

migrations/目录下创建SQL文件,例如1_initial.sql:

-- +migrate Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE people (id int);


-- +migrate Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP TABLE people;

其他嵌入式方法

使用实现http.FileSystem的库

migrationSource := &migrate.HttpFileSystemMigrationSource{
    FileSystem: httpFS,  // 任何实现http.FileSystem的库
}

内存中的迁移

migrations := &migrate.MemoryMigrationSource{
    Migrations: []*migrate.Migration{
        &migrate.Migration{
            Id:   "123",
            Up:   []string{"CREATE TABLE people (id int)"},
            Down: []string{"DROP TABLE people"},
        },
    },
}

特点

  • 支持SQLite、PostgreSQL、MySQL、MSSQL和Oracle数据库
  • 可以嵌入迁移到应用程序中
  • 迁移使用SQL定义,灵活性高
  • 原子性迁移
  • 支持向上/向下迁移以允许回滚
  • 支持一个项目中多种数据库类型

注意事项

  • 迁移文件按文件名排序执行,建议使用递增版本号或时间戳作为文件名前缀
  • 默认每个迁移在事务中运行以保证原子性
  • 对于不能在事务中执行的SQL命令,可以使用notransaction选项

通过以上方法,你可以轻松地将数据库迁移文件嵌入到Go应用程序中,实现自包含的部署。


更多关于golang数据库迁移工具插件sql-migrate支持嵌入式迁移文件的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang数据库迁移工具插件sql-migrate支持嵌入式迁移文件的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 数据库迁移工具 sql-migrate 嵌入式迁移文件使用指南

sql-migrate 是一个流行的 Go 语言数据库迁移工具,它支持将 SQL 迁移文件嵌入到 Go 二进制文件中,这在部署时非常有用。下面我将详细介绍如何使用 sql-migrate 的嵌入式迁移文件功能。

基本概念

嵌入式迁移文件允许你将 SQL 迁移脚本直接编译到 Go 二进制文件中,而不是作为外部文件存在。这有以下优势:

  • 简化部署(只需一个二进制文件)
  • 防止迁移文件被意外修改或删除
  • 更安全地管理数据库变更

安装 sql-migrate

首先安装 sql-migrate:

go get github.com/rubenv/sql-migrate/...

使用嵌入式迁移文件

1. 准备迁移文件

创建迁移文件目录结构,例如:

migrations/
├── 1_init.up.sql
├── 1_init.down.sql
├── 2_add_users.up.sql
└── 2_add_users.down.sql

2. 使用 go:embed 嵌入文件

在 Go 1.16+ 中,可以使用 //go:embed 指令嵌入文件:

package main

import (
	"embed"
	"database/sql"
	"log"
	"net/http"

	"github.com/rubenv/sql-migrate"
)

//go:embed migrations/*.sql
var migrations embed.FS

func main() {
	// 数据库连接
	db, err := sql.Open("mysql", "user:password@/dbname")
	if err != nil {
		log.Fatal(err)
	}

	// 创建迁移源
	migrationSource := &migrate.EmbedFileSystemMigrationSource{
		FileSystem: migrations,
		Root:       "migrations",
	}

	// 执行迁移
	n, err := migrate.Exec(db, "mysql", migrationSource, migrate.Up)
	if err != nil {
		log.Fatalf("迁移失败: %v", err)
	}
	log.Printf("应用了 %d 个迁移\n", n)

	// 其他应用代码...
}

3. 使用 AssetMigrationSource (旧方法)

如果你使用的是较旧的 Go 版本或 go-bindata 工具:

package main

import (
	"database/sql"
	"log"

	"github.com/rubenv/sql-migrate"
)

// 假设你使用 go-bindata 生成了 assets
// go-bindata -pkg main -o bindata.go migrations/...

func main() {
	db, err := sql.Open("mysql", "user:password@/dbname")
	if err != nil {
		log.Fatal(err)
	}

	migrations := &migrate.AssetMigrationSource{
		Asset:    Asset,
		AssetDir: AssetDir,
		Dir:      "migrations",
	}

	n, err := migrate.Exec(db, "mysql", migrations, migrate.Up)
	if err != nil {
		log.Fatalf("迁移失败: %v", err)
	}
	log.Printf("应用了 %d 个迁移\n", n)
}

高级用法

自定义迁移表名

migrate.SetTable("custom_migrations")

使用事务

n, err := migrate.ExecMax(db, "mysql", migrationSource, migrate.Up, 0)

只执行特定数量的迁移

// 只执行最多2个迁移
n, err := migrate.ExecMax(db, "mysql", migrationSource, migrate.Up, 2)

回滚迁移

// 回滚最近的一个迁移
n, err := migrate.Exec(db, "mysql", migrationSource, migrate.Down)

迁移文件命名规范

sql-migrate 遵循以下命名约定:

  • <version>_<description>.up.sql - 升级迁移
  • <version>_<description>.down.sql - 回滚迁移

版本可以是数字或日期格式:

  • 1_init.up.sql
  • 202201010000_add_users.up.sql

最佳实践

  1. 每个迁移应该是幂等的
  2. 总是提供对应的 down 迁移
  3. 在开发环境中频繁测试迁移
  4. 在生产环境执行前备份数据库
  5. 将迁移作为部署流程的一部分

完整示例

package main

import (
	"database/sql"
	"embed"
	"log"

	_ "github.com/go-sql-driver/mysql"
	"github.com/rubenv/sql-migrate"
)

//go:embed migrations/*.sql
var fs embed.FS

func main() {
	// 初始化数据库连接
	db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname?parseTime=true")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 设置迁移源
	migrations := &migrate.EmbedFileSystemMigrationSource{
		FileSystem: fs,
		Root:       "migrations",
	}

	// 执行所有待处理的迁移
	applied, err := migrate.Exec(db, "mysql", migrations, migrate.Up)
	if err != nil {
		log.Fatalf("迁移失败: %v", err)
	}

	log.Printf("成功应用了 %d 个迁移\n", applied)
}

通过这种方式,你可以轻松地将数据库迁移与你的 Go 应用程序一起打包和部署,确保数据库结构与应用程序版本保持同步。

回到顶部