golang实现PostgreSQL数据库迁移管理插件库go-pg-migrations的使用

go-pg-migrations 使用指南

go-pg-migrations 是一个用于在 Go 语言中管理 PostgreSQL 数据库迁移的库,基于 go-pg/pg 库构建。

安装

由于 go-pg 现在支持 Go 模块,go-pg-migrations 也支持模块。它目前依赖于 go-pg 的 v10 版本。在带有 go.mod 的项目中使用以下命令安装:

$ go get github.com/robinjoseph08/go-pg-migrations/v3

如果你还没有使用 Go 模块,仍然可以使用该包的 v1 版本。

使用示例

基本用法

创建一个 main 包(例如 example),调用 migrations.Run 并传入迁移文件保存目录、*pg.DB 实例和 os.Args:

package main

import (
	"log"
	"os"

	"github.com/go-pg/pg/v10"
	"github.com/robinjoseph08/go-pg-migrations/v3"
)

func main() {
	db := pg.Connect(&pg.Options{
		Addr:     "localhost:5432",
		User:     "postgres",
		Password: "postgres",
		Database: "test",
	})

	err := migrations.Run(db, "example", os.Args)
	if err != nil {
		log.Fatalln(err)
	}
}

命令示例

创建迁移文件:

$ go run example/*.go create create_users_table
Creating example/20180812001528_create_users_table.go...

运行迁移:

$ go run example/*.go migrate
Running batch 1 with 1 migration(s)...
Finished running "20180812001528_create_users_table"

查看迁移状态:

$ go run example/*.go status
+---------+-----------------------------------+-------+
| Applied | Migration                         | Batch |
+---------+-----------------------------------+-------+
|    √    | 20180812001528_create_users_table |     1 |
+---------+-----------------------------------+-------+

回滚迁移:

$ go run example/*.go rollback
Rolling back batch 1 with 1 migration(s)...
Finished rolling back "20180812001528_create_users_table"

获取帮助:

$ go run example/*.go help
Usage:
  go run example/*.go [command]

Commands:
  create   - create a new migration in example with the provided name
  migrate  - run any migrations that haven't been run yet
  rollback - roll back the previous run batch of migrations
  status   - show the status of each migration
  help     - print this help text

Examples:
  go run example/*.go create create_users_table
  go run example/*.go migrate
  go run example/*.go rollback
  go run example/*.go status
  go run example/*.go help

迁移文件示例

创建迁移文件时会生成如下模板:

package example

import (
	"github.com/go-pg/pg/v10"
	"github.com/go-pg/pg/v10/orm"
	migrations "github.com/robinjoseph08/go-pg-migrations/v3"
)

func init() {
	up := func(db orm.DB) error {
		_, err := db.Exec("")
		return err
	}

	down := func(db orm.DB) error {
		_, err := db.Exec("")
		return err
	}

	opts := migrations.MigrationOptions{}

	migrations.Register("20180812001528_create_users_table", up, down, opts)
}

生产环境部署

在生产环境中,可以编译单独的迁移二进制文件并部署:

# Dockerfile
FROM golang:1.13.3 as build

WORKDIR /app

COPY go.mod go.mod
COPY go.sum go.sum
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -installsuffix cgo -ldflags '-w -s' -o ./bin/serve ./cmd/serve
RUN CGO_ENABLED=0 GOOS=linux go build -installsuffix cgo -ldflags '-w -s' -o ./bin/migrations ./cmd/migrations

FROM alpine:3.8

RUN apk --no-cache add ca-certificates
COPY --from=build /app/bin /bin

CMD ["serve"]

构建并运行迁移:

$ docker build -t service:latest .
$ docker run --rm service:latest migrations migrate

特性

  1. 完整的迁移差异检查,确保不会遗漏任何迁移
  2. 基于时间戳的前缀,防止不同分支上的迁移版本冲突
  3. 可选择在事务中运行迁移
  4. 迁移锁定机制,防止并发迁移
  5. 批处理级别的回滚功能
  6. 明确的推荐工作流程

相比 go-pg/migrations,go-pg-migrations 提供了更健壮和安全的迁移体验。


更多关于golang实现PostgreSQL数据库迁移管理插件库go-pg-migrations的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现PostgreSQL数据库迁移管理插件库go-pg-migrations的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-pg-migrations实现PostgreSQL数据库迁移管理

go-pg-migrations是一个基于go-pg库的PostgreSQL数据库迁移管理工具,它可以帮助你轻松管理数据库schema的版本变更。下面我将详细介绍如何使用这个库。

安装

首先安装go-pg-migrations和依赖的go-pg库:

go get github.com/go-pg/migrations/v8
go get github.com/go-pg/pg/v10

基本用法

1. 创建迁移文件

迁移文件需要放在特定目录下,通常命名为migrations。每个迁移文件命名格式为:[版本号]_[描述].up.sql[版本号]_[描述].down.sql

例如:

  • migrations/001_init.up.sql - 初始化数据库
  • migrations/001_init.down.sql - 回滚初始化

2. 初始化迁移器

package main

import (
	"log"
	"os"

	"github.com/go-pg/migrations/v8"
	"github.com/go-pg/pg/v10"
)

func main() {
	db := pg.Connect(&pg.Options{
		Addr:     "localhost:5432",
		User:     "postgres",
		Password: "password",
		Database: "mydb",
	})
	defer db.Close()

	// 创建迁移器
	migrator := migrations.NewCollector()

	// 从文件系统加载迁移
	err := migrator.DiscoverSQLMigrations("migrations")
	if err != nil {
		log.Fatal(err)
	}

	// 运行迁移命令
	oldVersion, newVersion, err := migrator.Run(db, os.Args[1:]...)
	if err != nil {
		log.Fatal(err)
	}

	if newVersion != oldVersion {
		log.Printf("migrated from version %d to %d\n", oldVersion, newVersion)
	} else {
		log.Printf("version is %d\n", oldVersion)
	}
}

常用命令

编译上述代码后,可以通过命令行参数执行不同操作:

# 初始化迁移表
./migrator init

# 查看当前版本
./migrator version

# 升级到最新版本
./migrator up

# 升级到特定版本
./migrator up 2

# 回滚一个版本
./migrator down

# 回滚到特定版本
./migrator down 1

# 重置数据库(所有down迁移)
./migrator reset

迁移文件示例

001_init.up.sql

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    title TEXT NOT NULL,
    body TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

001_init.down.sql

DROP TABLE posts;
DROP TABLE users;

002_add_user_status.up.sql

ALTER TABLE users ADD COLUMN status TEXT DEFAULT 'active';

002_add_user_status.down.sql

ALTER TABLE users DROP COLUMN status;

使用Go代码定义迁移

除了SQL文件,你也可以用Go代码定义迁移:

func init() {
	migrations.Register(func(db migrations.DB) error {
		_, err := db.Exec(`
			CREATE TABLE products (
				id SERIAL PRIMARY KEY,
				name TEXT NOT NULL,
				price DECIMAL(10,2) NOT NULL
			)
		`)
		return err
	}, func(db migrations.DB) error {
		_, err := db.Exec("DROP TABLE products")
		return err
	})
}

高级用法

事务性迁移

默认情况下,每个迁移都在单独的事务中执行。你可以禁用此行为:

migrator.SetTableName("my_migrations") // 自定义迁移表名
migrator.DisableSQLMigrations()        // 禁用SQL迁移
migrator.DisableTx()                   // 禁用事务

自定义日志

migrator.SetLogger(logger) // 实现migrations.Logger接口

集成到现有项目

在实际项目中,你可以将迁移逻辑封装成单独的命令:

// cmd/migrate/main.go
package main

import (
	"log"
	"os"

	"github.com/go-pg/migrations/v8"
	"github.com/go-pg/pg/v10"
	"github.com/yourproject/internal/db"
)

func main() {
	migrator := migrations.NewCollector()
	err := migrator.DiscoverSQLMigrations("migrations")
	if err != nil {
		log.Fatal(err)
	}

	_, _, err = migrator.Run(db.GetDB(), os.Args[1:]...)
	if err != nil {
		log.Fatal(err)
	}
}

最佳实践

  1. 每个迁移文件只做一件事
  2. 确保down迁移能正确回滚up迁移的操作
  3. 在生产环境执行迁移前,先在测试环境验证
  4. 考虑使用版本控制来管理迁移文件
  5. 对于大型数据库,考虑将数据迁移与结构迁移分开

go-pg-migrations提供了一种简单而强大的方式来管理PostgreSQL数据库的变更,特别适合与go-pg/pg库一起使用。通过遵循上述模式,你可以轻松实现数据库的版本控制和团队协作。

回到顶部