Files
go-common/docs/migration.md

5.5 KiB
Raw Blame History

数据库迁移工具文档

概述

数据库迁移工具提供了数据库版本管理和迁移功能支持MySQL、PostgreSQL、SQLite等数据库。使用GORM作为数据库操作库可以方便地进行数据库结构的版本控制。

功能特性

  • 支持迁移版本管理
  • 支持迁移和回滚操作
  • 支持从文件系统加载迁移文件
  • 支持迁移状态查询
  • 自动创建迁移记录表
  • 事务支持,确保迁移的原子性

使用方法

1. 创建迁移器

import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "github.com/go-common/migration"
)

// 初始化数据库连接
dsn := "user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

// 创建迁移器
migrator := migration.NewMigrator(db)
// 或者指定自定义的迁移记录表名
migrator := migration.NewMigrator(db, "my_migrations")

2. 添加迁移

方式一:代码方式添加迁移

migrator.AddMigration(migration.Migration{
    Version:     "20240101000001",
    Description: "create_users_table",
    Up: func(db *gorm.DB) error {
        return db.Exec(`
            CREATE TABLE users (
                id INT PRIMARY KEY AUTO_INCREMENT,
                name VARCHAR(255) NOT NULL,
                email VARCHAR(255) UNIQUE NOT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        `).Error
    },
    Down: func(db *gorm.DB) error {
        return db.Exec("DROP TABLE IF EXISTS users").Error
    },
})

方式二:批量添加迁移

migrations := []migration.Migration{
    {
        Version:     "20240101000001",
        Description: "create_users_table",
        Up: func(db *gorm.DB) error {
            return db.Exec("CREATE TABLE users ...").Error
        },
        Down: func(db *gorm.DB) error {
            return db.Exec("DROP TABLE users").Error
        },
    },
    {
        Version:     "20240101000002",
        Description: "add_index_to_users",
        Up: func(db *gorm.DB) error {
            return db.Exec("CREATE INDEX idx_email ON users(email)").Error
        },
        Down: func(db *gorm.DB) error {
            return db.Exec("DROP INDEX idx_email ON users").Error
        },
    },
}
migrator.AddMigrations(migrations...)

方式三:从文件加载迁移

// 文件命名格式: {version}_{description}.sql 或 {version}_{description}.up.sql
// 例如: 20240101000001_create_users_table.up.sql
// 对应的回滚文件: 20240101000001_create_users_table.down.sql

migrations, err := migration.LoadMigrationsFromFiles("./migrations", "*.up.sql")
if err != nil {
    log.Fatal(err)
}

migrator.AddMigrations(migrations...)

3. 执行迁移

// 执行所有未应用的迁移
err := migrator.Up()
if err != nil {
    log.Fatal(err)
}

4. 回滚迁移

// 回滚最后一个迁移
err := migrator.Down()
if err != nil {
    log.Fatal(err)
}

5. 查看迁移状态

status, err := migrator.Status()
if err != nil {
    log.Fatal(err)
}

for _, s := range status {
    fmt.Printf("Version: %s, Description: %s, Applied: %v\n", 
        s.Version, s.Description, s.Applied)
}

6. 生成迁移版本号

// 生成基于时间戳的版本号
version := migration.GenerateVersion()
// 输出: 1704067200 (Unix时间戳)

API 参考

Migration 结构体

type Migration struct {
    Version     string              // 迁移版本号(必须唯一)
    Description string              // 迁移描述
    Up          func(*gorm.DB) error // 升级函数
    Down        func(*gorm.DB) error // 回滚函数(可选)
}

Migrator 方法

NewMigrator(db *gorm.DB, tableName ...string) *Migrator

创建新的迁移器。

参数:

  • db: GORM数据库连接
  • tableName: 可选,迁移记录表名,默认为 "schema_migrations"

返回: 迁移器实例

AddMigration(migration Migration)

添加单个迁移。

AddMigrations(migrations ...Migration)

批量添加迁移。

Up() error

执行所有未应用的迁移。按版本号升序执行。

返回: 错误信息

Down() error

回滚最后一个已应用的迁移。

返回: 错误信息

Status() ([]MigrationStatus, error)

查看所有迁移的状态。

返回: 迁移状态列表和错误信息

MigrationStatus 结构体

type MigrationStatus struct {
    Version     string // 版本号
    Description string // 描述
    Applied     bool   // 是否已应用
}

辅助函数

LoadMigrationsFromFiles(dir string, pattern string) ([]Migration, error)

从文件系统加载迁移文件。

参数:

  • dir: 迁移文件目录
  • pattern: 文件匹配模式,如 "*.up.sql"

返回: 迁移列表和错误信息

文件命名格式: {version}_{description}.up.sql

示例:

  • 20240101000001_create_users_table.up.sql - 升级文件
  • 20240101000001_create_users_table.down.sql - 回滚文件(可选)

GenerateVersion() string

生成基于时间戳的迁移版本号。

返回: Unix时间戳字符串

注意事项

  1. 迁移版本号必须唯一,建议使用时间戳格式
  2. 迁移操作在事务中执行,失败会自动回滚
  3. 迁移记录表会自动创建,无需手动创建
  4. 如果迁移文件没有对应的down文件回滚操作会失败
  5. 迁移按版本号升序执行,确保顺序正确

示例

完整示例请参考 examples/migration_example.go