golang简单易用的数据库迁移插件库migrator的使用

Golang简单易用的数据库迁移插件库migrator的使用

migrator logo

migrator是一个极其简单的Go数据库迁移库。

特性

  • 代码简单
  • 可作为库使用,可嵌入和扩展
  • 支持所有database/sql兼容的数据库
  • 支持Go代码迁移,可以是事务性的(migrator.Migration)或非事务性的(migrator.MigrationNoTx)
  • 不需要使用//go:embed,因为所有迁移都是Go代码

兼容性

虽然任何支持database/sql及其推荐驱动程序的数据库都应该可以正常工作,但目前仅明确测试了PostgreSQLMySQL

使用示例

以下示例假设:

  • 有一个工作的postgres数据库连接在localhost上,用户名为postgres,密码为空,数据库名为foo

快速开始

package main

import (
	"database/sql"
	"log"

	_ "github.com/jackc/pgx/v4/stdlib" // postgres驱动
	"github.com/lopezator/migrator"
)

func main() {
    // 配置迁移
    m, err := migrator.New(
        migrator.Migrations(
            &migrator.Migration{
                Name: "Create table foo",
                Func: func(tx *sql.Tx) error {
                    if _, err := tx.Exec("CREATE TABLE foo (id INT PRIMARY KEY)"); err != nil {
                        return err
                    }
                    return nil
                },
            },
        ),
    )
    if err != nil {
        log.Fatal(err)
    }
   
    // 打开数据库连接
    db, err := sql.Open("pgx", "postgres://postgres@localhost/foo?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
    
    // 执行迁移
    if err := m.Migrate(db); err != nil {
        log.Fatal(err)
    }
}

注意事项:

  • migrator创建/管理一个名为migrations的表来跟踪应用的版本。如果你想自定义表名,可以将migrator.TableName("my_migrations")作为额外选项传递给migrator.New函数。

日志记录

默认情况下,migrator将应用/已应用的迁移信息打印到stdout。如果你需要特殊格式或想使用第三方日志库,可以使用WithLogger选项:

logger := migrator.WithLogger(migrator.LoggerFunc(func(msg string, args ...interface{}) {
	// 你的日志代码
}))

然后你只需要将logger作为选项传递给migrator.New

更多示例

可以查看migrator_test.go文件获取更多示例。

不想在字符串中写复杂的迁移?

你仍然可以使用你喜欢的嵌入工具将迁移写在.sql文件中,然后加载到migrator中!

迁移顺序

为了避免不同标识符、ID冲突等问题,迁移的顺序就是传递给migrator的顺序。

没有回滚迁移?

添加回滚迁移的功能会增加API、代码的复杂性,并增加失去迁移列表与数据库当前状态同步的风险。此外,在某些情况下,并非所有迁移都可以轻松回滚或根本无法回滚。

我们建议遵循数据库迁移的"仅追加"哲学,因此纠正有缺陷的迁移是通过添加新迁移而不是回滚它来实现的。

注意事项

  • 迁移名称必须对你的数据库引擎是SQL安全的。建议避免使用冲突字符,如',否则你将不得不自己转义它们,例如PostgreSQL使用'',MySQL使用\'

动机

为什么需要另一个迁移库?

  • 轻量级实现,仅支持database/sql。Migrator不需要任何ORM或其他重型库作为依赖。它只是一个单文件,不到200行代码!
  • 易于嵌入到你的应用程序中,不需要安装/使用单独的二进制文件
  • 支持Go迁移,可以是事务性的或非事务性的
  • 灵活使用

这不是migrator的目标

  • 添加对database/sql之外的数据库的支持
  • 为了添加可以在用户端轻松实现的功能而使代码/逻辑复杂化,如查看当前版本、已应用版本列表等
  • 添加一堆依赖项只是为了提供CLI/独立功能

贡献

欢迎提交Pull Request,这是一个早期实现,所有领域都需要工作:文档、示例、测试、CI…

最简单的方法是安装dockerdocker-compose,并确保在提交PR之前运行以下命令以符合代码标准并通过所有测试:

$> docker-compose up -d --build
$> docker-compose exec migrator make prepare
$> docker-compose exec migrator make sanity-check
$> docker-compose exec migrator make test
$> docker-compose down

Logo

Logo来自@ashleymcnamara的gophers仓库。我只是对它做了轻微的修改。


更多关于golang简单易用的数据库迁移插件库migrator的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang简单易用的数据库迁移插件库migrator的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang数据库迁移插件库migrator使用指南

migrator是一个简单易用的Golang数据库迁移工具库,它支持多种数据库,提供了简洁的API来管理数据库结构变更。下面我将详细介绍如何使用migrator进行数据库迁移。

安装

首先安装migrator库:

go get -u github.com/golang-migrate/migrate/v4

根据你使用的数据库,还需要安装对应的驱动:

# PostgreSQL
go get -u github.com/golang-migrate/migrate/v4/database/postgres
go get -u github.com/lib/pq

# MySQL
go get -u github.com/golang-migrate/migrate/v4/database/mysql
go get -u github.com/go-sql-driver/mysql

# SQLite
go get -u github.com/golang-migrate/migrate/v4/database/sqlite3

基本使用

1. 初始化迁移

首先创建迁移文件目录,通常命名为migrations。在该目录下创建迁移文件,命名格式为<version>_<name>.up.sql<version>_<name>.down.sql

例如:

  • 0001_create_users_table.up.sql
  • 0001_create_users_table.down.sql

2. 编写迁移文件

up.sql文件包含要执行的SQL语句,down.sql包含回滚操作。

示例0001_create_users_table.up.sql:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

对应的0001_create_users_table.down.sql:

DROP TABLE IF EXISTS users;

3. 在Go代码中使用

package main

import (
	"database/sql"
	"log"

	"github.com/golang-migrate/migrate/v4"
	"github.com/golang-migrate/migrate/v4/database/postgres"
	_ "github.com/golang-migrate/migrate/v4/source/file"
	_ "github.com/lib/pq"
)

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

	// 创建数据库驱动实例
	driver, err := postgres.WithInstance(db, &postgres.Config{})
	if err != nil {
		log.Fatal(err)
	}

	// 创建migrate实例
	m, err := migrate.NewWithDatabaseInstance(
		"file://migrations",
		"postgres", driver)
	if err != nil {
		log.Fatal(err)
	}

	// 执行迁移
	err = m.Up()
	if err != nil && err != migrate.ErrNoChange {
		log.Fatal(err)
	}

	log.Println("Migration done")
}

常用操作

执行特定数量的迁移

// 执行2个迁移
err = m.Steps(2)
if err != nil {
	log.Fatal(err)
}

回滚迁移

// 回滚1个迁移
err = m.Steps(-1)
if err != nil {
	log.Fatal(err)
}

// 回滚所有迁移
err = m.Down()
if err != nil {
	log.Fatal(err)
}

强制版本号

当迁移出现问题时,可以强制设置版本号:

err = m.Force(2) // 强制设置为版本2
if err != nil {
	log.Fatal(err)
}

最佳实践

  1. 版本控制:将迁移文件纳入版本控制系统
  2. 原子性:每个迁移应该是原子的,要么完全成功,要么完全失败
  3. 可逆性:每个迁移都应该有对应的回滚操作
  4. 测试:在生产环境使用前,先在测试环境测试迁移
  5. 备份:执行重要迁移前备份数据库

高级特性

使用Go代码作为迁移

除了SQL文件,migrator还支持用Go代码编写迁移:

// 创建迁移文件
migrate.Create("migrations", "create_users_table")

// 生成的go文件示例
func Up(tx *sql.Tx) error {
	_, err := tx.Exec("CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255))")
	return err
}

func Down(tx *sql.Tx) error {
	_, err := tx.Exec("DROP TABLE users")
	return err
}

使用不同的源

除了文件系统,migrator还支持从其他源读取迁移:

// 从GitHub读取
m, err := migrate.New(
	"github://owner/repo/path/to/migrations#ref",
	"postgres://user:password@localhost:5432/database?sslmode=disable")

总结

migrator是一个功能强大且灵活的数据库迁移工具,通过简单的API和文件结构,可以轻松管理数据库的版本变更。它的主要优点包括:

  1. 支持多种数据库
  2. 简单易用的命令行和API
  3. 支持SQL和Go代码两种迁移方式
  4. 完善的版本控制和回滚机制

通过合理使用migrator,可以大大简化数据库结构变更的管理工作,提高开发效率。

回到顶部