# DB Migration Patterns

> 数据库迁移与版本控制规范。当用户需要修改数据库表结构、添加索引、处理数据迁移，或询问如何安全地在生产环境执行 DDL 变更时使用此 skill。

- Skill: `migoxlab/db-migration-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add migoxlab/db-migration-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/migoxlab/db-migration-patterns/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: migoxlab (https://skillmd.com/u/migoxlab)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/migoxlab/db-migration-patterns

---


# 数据库迁移与版本控制 Skill

## 描述

这个 skill 帮助开发者规范地管理数据库结构的变更。通过代码化的迁移脚本（Migrations），确保数据库变更在开发、测试、生产环境中的一致性、可追溯性和安全性，避免手动执行 SQL 带来的风险。

## 何时使用

在以下场景中使用这个 skill：
- AI 协助设计或修改数据库表结构时
- 用户需要添加、删除字段或索引时
- 项目需要引入数据库版本控制工具（如 golang-migrate, goose, gorm migration）时
- 用户询问如何实现零宕机（Zero-downtime）的数据库变更时

## 核心设计原则

### 1. 迁移脚本规范 (Migration Scripts)

所有的 DDL（数据定义语言）和必要的 DML（数据操作语言）必须通过版本化的迁移脚本执行。

- **命名规范**：`版本号_描述.up.sql` 和 `版本号_描述.down.sql`
  - 版本号建议使用时间戳：`20231025143000_add_user_status.up.sql`
  - 描述应简明扼要，使用下划线分隔。
- **成对出现**：每个 `up` 脚本（升级）必须有一个对应的 `down` 脚本（回滚）。
- **不可变性**：一旦迁移脚本提交并合并到主分支，**绝对禁止**修改该脚本。如果需要调整，必须创建一个新的迁移脚本。

### 2. 零宕机变更策略 (Zero-Downtime Migrations)

在生产环境中，直接修改表结构（特别是大表）可能导致锁表和业务中断。必须采用向后兼容的变更策略。

#### 场景 A：添加新字段
1. **步骤 1**：添加新字段，**必须允许 NULL** 或设置默认值。
2. **步骤 2**：更新代码，使其能够读写新字段。

#### 场景 B：重命名字段或修改字段类型
**严禁直接使用 `ALTER TABLE RENAME/MODIFY`。**
1. **步骤 1**：添加新字段（新名称或新类型）。
2. **步骤 2**：更新代码，实现**双写**（同时写入老字段和新字段），读取时优先读老字段。
3. **步骤 3**：执行数据迁移脚本（Backfill），将老字段的数据刷入新字段。
4. **步骤 4**：更新代码，改为只读写新字段。
5. **步骤 5**：在未来的版本中，通过迁移脚本删除老字段。

#### 场景 C：添加索引
- 在 MySQL/PostgreSQL 中，添加索引可能阻塞写操作。
- 必须使用并发/在线建索引语法：
  - MySQL: `ALGORITHM=INPLACE, LOCK=NONE`
  - PostgreSQL: `CREATE INDEX CONCURRENTLY`

### 3. 常见工具推荐

在 Go 生态中，推荐使用以下工具管理迁移：
- [golang-migrate/migrate](https://github.com/golang-migrate/migrate)：最流行，支持 CLI 和代码内嵌。
- [pressly/goose](https://github.com/pressly/goose)：支持 SQL 和 Go 代码编写迁移逻辑。

### 4. 迁移脚本编写示例 (以 MySQL 为例)

**UP 脚本 (`20231025143000_add_user_status.up.sql`)**:
```sql
ALTER TABLE `users` 
ADD COLUMN `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态: 1-正常 2-封禁' AFTER `email`;

CREATE INDEX `idx_status` ON `users` (`status`);
```

**DOWN 脚本 (`20231025143000_add_user_status.down.sql`)**:
```sql
ALTER TABLE `users` DROP INDEX `idx_status`;
ALTER TABLE `users` DROP COLUMN `status`;
```

## AI 交互指导

当 AI 协助生成数据库变更 SQL 或迁移代码时，必须：
1. **强制要求**提供 UP 和 DOWN 两部分逻辑。
2. 检查添加的字段是否具备合理的默认值或允许 NULL，以防破坏现有插入逻辑。
3. 如果检测到用户试图直接重命名字段或修改类型，**必须警告**其风险，并建议使用上述的“双写+数据回填”策略。
4. 提醒用户在建索引时注意锁表风险，推荐使用在线建索引语法。

