数据库迁移设计(golang-migrate)

用版本化 up/down SQL 管理 schema:与 GORM AutoMigrate 的分工、迁移文件组织、启动执行策略与回滚边界。

#type / concept #status / growing #tech / dev / backend #resource / go

[!info] 关联笔记

数据库迁移设计(golang-migrate)

这个概念为什么出现

多人协作改表时若靠:

  • 手工执行 SQL → 环境不一致
  • AutoMigrate → 难删列、难改类型、难做数据迁移

版本化迁移让每次 schema 变更有编号、可审查、可在 CI/CD 重放,并在理想情况下可回滚。

[!abstract] 一句话理解 每个变更一对 up/down SQL(或等价脚本),工具记录已应用版本;应用启动或发布流水线执行 up,出问题再评估 down

最小文件布局

migrations/
  000001_init.up.sql
  000001_init.down.sql
  000002_add_users_email.up.sql
  000002_add_users_email.down.sql
-- 000001_init.up.sql
CREATE TABLE users (
  id UUID PRIMARY KEY,
  name TEXT NOT NULL
);
-- 000001_init.down.sql
DROP TABLE IF EXISTS users;

工具示例:golang-migrate(社区主流之一,非标准库)。

migrate -path ./migrations -database "$DATABASE_URL" up
migrate -path ./migrations -database "$DATABASE_URL" version

核心概念

版本表

工具在库中维护 schema_migrations(名因工具而异),记录当前版本,避免重复执行。

up / down

updown
含义应用变更撤销变更
生产常规路径常难完美,需评估数据损失

并非所有迁移都值得 down(删表、不可逆数据转换)。文档写清风险。

与 AutoMigrate

迁移文件AutoMigrate
审查Git diff SQL隐式
删列/改类型显式弱/不可
数据回填可写 SQL不适合
原型速度慢一点

推荐:开发可 AutoMigrate 探索,发布路径用版本迁移

何时执行

  1. CD 独立 Job:先 migrate 再滚新版本(推荐)
  2. 应用启动时:简单但多副本并发需工具锁
  3. 禁止每个实例无锁乱跑

设计动机

基础设施即代码:schema 与应用版本协同,可重建环境。

边界与反直觉

  1. 锁与并发:多副本启动 migrate 需保证单飞。
  2. 长锁迁移:大表 ALTER 可能锁表,需在线策略(pt-osc 等,因库而异)。
  3. expand/contract:先加列兼容旧代码,再切读,再删旧列——跨多版本发布。
  4. 种子数据与迁移分离,避免环境脏耦合。

常见误区

[!warning] 只靠 AutoMigrate 上生产
缺少可审 SQL 与可控回滚。

[!warning] 编辑已发布的旧迁移文件
已上环境的版本应不可变;再开新版本。

[!warning] down 当儿戏
生产回滚先备份;很多团队只 forward-fix。

工程实践

  1. 文件名单调递增、团队统一编号规则
  2. PR 必须含迁移与回滚说明
  3. CI 对空库 up 全量跑通
  4. 与应用兼容:先部署兼容旧 schema 的代码,或先迁移再部署(按变更类型)
  5. 权限:迁移账号与运行时账号分离

可验证实验

  1. 空库连续 up,查版本表。
  2. up 应 no-op。
  3. 新开 000003,观察只应用增量。
  4. 故意改已应用文件,理解 checksum 失败(若工具支持)。

本节总结

  • 本质:schema 变更的版本控制。
  • 关键:不可变历史、发布路径显式、与 ORM 分工。
  • 下一步database-sql-in-go 仓储实现;go-docker-deployment 中挂迁移 Job。

自测题

  1. 为什么已合并的迁移文件不应改内容?
  2. expand/contract 解决什么发布问题?
  3. 多副本同时 migrate 的风险?
答案
  1. 已部署环境 checksum/版本历史会冲突。
  2. 零停机下新旧代码并存时的列兼容。
  3. 竞态执行、锁失败、重复或半应用状态。

延伸阅读


笔记元信息

  • 文件:database-migration-golang-migrate.md
  • 状态:已深化
创建于 2026/6/25 更新于 2026/7/15