1. GORM 迁移概述
1.1 什么是数据库迁移
数据库迁移(Database Migration)是指对数据库 Schema(表结构、索引、约束等)进行版本化、可追溯的变更管理。在应用开发过程中,模型定义会随业务需求不断调整,而数据库迁移正是将模型变更同步到数据库的规范化手段。
核心目标:让数据库 Schema 始终与代码中的模型定义保持一致,同时支持团队协作、回滚和审计。
迁移通常包含以下操作类型:
| 操作类型 | 说明 | 示例 |
|---|---|---|
| 创建表 | 根据模型定义新建数据库表 | CREATE TABLE users (...) |
| 新增字段 | 为已有表添加列 | ALTER TABLE users ADD COLUMN age INT |
| 修改字段 | 变更列类型、默认值或约束 | ALTER TABLE users MODIFY COLUMN name VARCHAR(100) |
| 删除字段 | 移除不再使用的列 | ALTER TABLE users DROP COLUMN temp_field |
| 添加索引 | 为查询性能创建索引 | CREATE INDEX idx_email ON users(email) |
| 删除索引 | 移除冗余索引 | DROP INDEX idx_email ON users |
提示:在生产环境中,手动执行 DDL 语句风险较高,推荐使用迁移工具(如 GORM AutoMigrate、golang-migrate、Flyway)来保证变更的可控性和可重复性。
1.2 GORM AutoMigrate 简介
GORM 提供了 AutoMigrate 方法,用于自动将 Go 结构体模型与数据库表结构进行同步。它会在启动时检查数据库中是否存在对应的表,并根据模型定义自动创建表、添加字段和索引。
// 基本用法
db.AutoMigrate(&User{}, &Product{}, &Order{})
// 模型定义示例
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:255"`
Age int `gorm:"default:0"`
CreatedAt time.Time
UpdatedAt time.Time
}
注意:AutoMigrate 只会新增表和字段,不会删除已存在的字段或表。如需删除操作,需手动执行迁移脚本或使用第三方迁移工具。
AutoMigrate 的核心特性:
- 自动建表:根据模型定义自动生成
CREATE TABLE语句 - 字段追加:检测到模型新增字段时,自动执行
ALTER TABLE添加列 - 索引管理:根据标签(如
uniqueIndex、index)自动创建索引 - 外键约束:支持通过标签或嵌套结构自动建立外键关系
- 表名映射:默认使用结构体名的蛇形复数形式作为表名,支持自定义
| 特性 | 支持情况 | 说明 |
|---|---|---|
| 创建表 | ✅ 完全支持 | 表不存在时自动创建 |
| 新增字段 | ✅ 完全支持 | 仅追加,不影响已有数据 |
| 修改字段 | ⚠️ 部分支持 | 需配合 gorm:"type:..." 标签 |
| 删除字段 | ❌ 不支持 | 需手动执行 DDL |
| 删除表 | ❌ 不支持 | 需手动执行 DDL |
| 索引变更 | ✅ 支持新增 | 不删除已有索引 |
1.3 迁移与契约校验的关系
在微服务架构和数据密集型应用中,数据库 Schema 本身就是一种契约——它定义了数据的形状、类型和约束。迁移与契约校验的关系体现在以下三个层面:
- 结构契约:模型定义(Go struct)与数据库表结构之间的双向一致性校验
- 类型契约:Go 数据类型与数据库列类型之间的映射正确性校验
- 约束契约:非空、唯一、默认值、外键等约束条件的完整性校验
核心观点:迁移是契约的执行过程,校验是契约的验证过程。两者结合才能确保数据层的可靠性和可维护性。
迁移与契约校验的对比:
| 维度 | 数据库迁移 | 契约校验 |
|---|---|---|
| 关注点 | Schema 变更的执行 | Schema 一致性的验证 |
| 执行时机 | 应用启动 / 部署时 | 开发阶段 / CI 流程 / 运行时 |
| 输出 | DDL 语句执行结果 | 校验通过 / 失败报告 |
| 风险 | 数据丢失、表结构冲突 | 模型与数据库不一致导致运行时错误 |
| GORM 支持 | AutoMigrate / Migrator 接口 | 需自定义校验逻辑或使用第三方库 |
实践建议:在 CI/CD 流程中加入契约校验步骤,确保模型定义与数据库 Schema 一致后再执行迁移,可以有效避免生产环境的结构冲突问题。