325 lines
7.9 KiB
Markdown
325 lines
7.9 KiB
Markdown
# 数据库迁移工具文档
|
||
|
||
## 概述
|
||
|
||
数据库迁移工具提供了数据库版本管理和迁移功能,支持MySQL、PostgreSQL、SQLite等数据库。使用GORM作为数据库操作库,可以方便地进行数据库结构的版本控制。
|
||
|
||
## 功能特性
|
||
|
||
- 支持迁移版本管理
|
||
- 支持迁移和回滚操作
|
||
- 支持从文件系统加载迁移文件
|
||
- 支持迁移状态查询
|
||
- 自动创建迁移记录表
|
||
- 事务支持,确保迁移的原子性
|
||
|
||
## 使用方法
|
||
|
||
### 1. 创建迁移器
|
||
|
||
```go
|
||
import (
|
||
"gorm.io/driver/mysql"
|
||
"gorm.io/gorm"
|
||
"git.toowon.com/jimmy/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. 添加迁移
|
||
|
||
#### 方式一:代码方式添加迁移
|
||
|
||
```go
|
||
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
|
||
},
|
||
})
|
||
```
|
||
|
||
#### 方式二:批量添加迁移
|
||
|
||
```go
|
||
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...)
|
||
```
|
||
|
||
#### 方式三:从文件加载迁移
|
||
|
||
```go
|
||
// 文件命名格式: {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. 执行迁移
|
||
|
||
```go
|
||
// 执行所有未应用的迁移
|
||
err := migrator.Up()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
```
|
||
|
||
### 4. 回滚迁移
|
||
|
||
```go
|
||
// 回滚最后一个迁移
|
||
err := migrator.Down()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
```
|
||
|
||
### 5. 查看迁移状态
|
||
|
||
```go
|
||
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. 重置迁移
|
||
|
||
#### 方式一:仅清空迁移记录(不回滚数据库变更)
|
||
|
||
```go
|
||
// 直接调用(需要传入确认标志)
|
||
err := migrator.Reset(true)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 交互式确认(推荐,会提示警告信息)
|
||
err := migrator.ResetWithConfirm()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
```
|
||
|
||
#### 方式二:回滚所有迁移并清空记录
|
||
|
||
```go
|
||
// 直接调用(需要传入确认标志)
|
||
err := migrator.ResetAll(true)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 交互式确认(推荐,会提示警告信息)
|
||
err := migrator.ResetAllWithConfirm()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
```
|
||
|
||
**注意:**
|
||
- `Reset()` 仅清空迁移记录表,不会回滚已执行的数据库变更
|
||
- `ResetAll()` 会回滚所有已应用的迁移(执行Down函数),然后清空记录
|
||
- 交互式方法会显示详细的警告信息,需要输入确认文本才能执行
|
||
|
||
### 7. 生成迁移版本号
|
||
|
||
```go
|
||
// 生成基于时间戳的版本号
|
||
version := migration.GenerateVersion()
|
||
// 输出: 1704067200 (Unix时间戳)
|
||
```
|
||
|
||
## API 参考
|
||
|
||
### Migration 结构体
|
||
|
||
```go
|
||
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)
|
||
|
||
查看所有迁移的状态。
|
||
|
||
**返回:** 迁移状态列表和错误信息
|
||
|
||
#### Reset(confirm bool) error
|
||
|
||
重置所有迁移记录(仅清空记录表,不回滚数据库变更)。
|
||
|
||
**参数:**
|
||
- `confirm`: 确认标志,必须为true才能执行
|
||
|
||
**返回:** 错误信息
|
||
|
||
**注意:** 此操作只清空迁移记录,不会回滚已执行的迁移操作。如果需要回滚迁移,请先使用Down方法逐个回滚。
|
||
|
||
#### ResetWithConfirm() error
|
||
|
||
交互式重置所有迁移记录(带确认提示)。
|
||
|
||
**返回:** 错误信息
|
||
|
||
**说明:** 会显示警告信息,需要输入"RESET"(全大写)才能执行。
|
||
|
||
#### ResetAll(confirm bool) error
|
||
|
||
重置所有迁移并回滚所有已应用的迁移。
|
||
|
||
**参数:**
|
||
- `confirm`: 确认标志,必须为true才能执行
|
||
|
||
**返回:** 错误信息
|
||
|
||
**注意:** 此操作会回滚所有已应用的迁移(执行Down函数),然后清空迁移记录。操作不可逆,请谨慎使用。
|
||
|
||
#### ResetAllWithConfirm() error
|
||
|
||
交互式重置所有迁移并回滚(带确认提示)。
|
||
|
||
**返回:** 错误信息
|
||
|
||
**说明:** 会显示警告信息,需要输入"RESET ALL"(全大写)才能执行。
|
||
|
||
### MigrationStatus 结构体
|
||
|
||
```go
|
||
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. **执行顺序**:迁移按版本号升序执行,确保顺序正确
|
||
6. **重置操作**:
|
||
- `Reset()` 只清空迁移记录,不会回滚数据库变更
|
||
- `ResetAll()` 会回滚所有迁移,操作不可逆
|
||
- 建议使用交互式方法(`ResetWithConfirm`、`ResetAllWithConfirm`)以确保安全
|
||
- 在生产环境使用重置功能前,请确保已备份数据库
|
||
|
||
## 示例
|
||
|
||
完整示例请参考 `examples/migration_example.go`
|
||
|