用 golang-migrate 管理 Go 项目的数据库迁移
golang-migrate 是 Go 生态主流迁移工具:up/down 迁移文件、CLI 与库两种用法、版本表追踪、脏版本恢复、CI/CD 集成。本文从概念到生产实践全覆盖。
本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。
直接回答:golang-migrate 用成对的 up/down SQL 文件管理 schema 演进——migrate create 生成版本化文件,migrate up 按序应用,数据库里的 schema_migrations 表追踪当前版本;支持 CLI 独立运行或作为库嵌入应用启动流程,脏版本必须先人工修复实际 schema,再用 force 校正版本标记。
为什么需要迁移系统
数据库 schema 的版本控制:直接手改生产库是高风险操作,迁移把变更变成可追踪、可重复执行部署流程的序列——开发、测试、生产环境用同一套文件推进到同一状态。
安装与创建迁移
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
migrate create -ext sql -dir migrations -seq add_users_table
生成 000001_add_users_table.up.sql 与 000001_add_users_table.down.sql——up 写变更,down 写回滚,两个都要认真写。
CLI 运行与管理
migrate -path migrations -database "$DATABASE_URL" version
migrate -path migrations -database "$DATABASE_URL" up
# 确认数据备份和回退计划后,才执行 down 1 或 force N
脏版本:迁移执行一半失败会置 dirty 标志,后续 up/down 等迁移操作会受阻。修复姿势:检查备份与数据库事务状态,完成或撤销部分变更,再 force 到实际 schema 对应的版本。force 不运行 SQL,也不会修复数据。DATABASE_URL 使用受保护的凭据及数据库要求的 TLS 配置,不把 sslmode=disable 复制到生产。
嵌入 Go 应用与 CI/CD
作为库集成时先用 migrate.New(...) 构造实例,再调用 m.Up(),正确处理 migrate.ErrNoChange 和其他错误,并关闭资源。这不保证应用与 schema 自动兼容。CI/CD 里建议独立迁移步骤先于应用部署——迁移成功才滚动更新应用,避免多实例并发迁移(工具有数据库锁,但部署顺序仍要正确)。 部署记录中保留迁移前后版本与执行结果,并用关键读写请求验证新旧应用兼容性。
常见问题(FAQ)
Q:迁移失败的回滚是自动的吗?
A:不是。up 文件执行失败会留脏版本,工具不会自动跑 down——人介入判断现场,修好后 force 版本再继续。
Q:生产环境该用 up 全部还是逐版本?
A:小步快跑场景 up 即可;大版本跨越建议逐版本执行并逐版本验证,问题定位更精准。
Q:down 文件可以不写吗?
A:技术上能跑,但等于放弃回滚能力。破坏性变更未必有可恢复数据的 down;应明确不可逆步骤,采用备份恢复或向前修复,并用扩展-收缩迁移兼容滚动部署中的新旧应用。
官方参考
资料核对日期:2026-09-29。