Go 数据库迁移实战:用 golang-migrate 做版本化、可回滚的表结构演进
test12026-10-121 次阅读
为什么不用代码里自动建表
手写 CREATE TABLE 散落在初始化函数里,既看不到历史,也回不去。golang-migrate 把每次结构变更写成一对 up/down SQL 文件,带递增版本号,向上迁移和向下回滚都有据可查。
编写迁移文件
文件名格式为 {版本}_{名称}.up.sql 与 .down.sql。例如新增 users 表:
-- 000001_create_users.up.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(120) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 000001_create_users.down.sql
DROP TABLE IF EXISTS users;
在程序启动时执行迁移
用 migrate 库驱动,支持 file:// 与数据库直连。下面用 Go 代码在启动期把数据库拉到最新版本。
package main
import (
"flag"
"log"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
func main() {
dsn := flag.String("db", "postgres://app:pass@localhost:5432/app?sslmode=disable", "数据库连接")
flag.Parse()
m, err := migrate.New(
"file://db/migrations",
*dsn,
)
if err != nil {
log.Fatalf("migrate new: %v", err)
}
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
log.Fatalf("migrate up: %v", err)
}
log.Println("数据库迁移完成")
}
回滚与版本管理
- 开发期用 m.Steps(-1) 回退一步,生产环境回滚要谨慎,建议和代码版本一起走发布流程。
- 迁移文件一旦合入主干不要修改,需要变更就新增更高版本号的文件,保证多环境一致。
- CI 里加一步 migrate up 到测试库,提前暴露 SQL 语法和约束冲突。
- 大表加字段尽量用 ALTER TABLE ... ADD COLUMN 配合默认值或后台批量回填,避免长锁。
T
test1
文章作者
为什么不用代码里自动建表 手写 CREATE TABLE 散落在初始化函数里,既看不到历史,也回不去。golang-m...
- 分类
- 技术
- 发布时间
- 2026-10-12
- 字数
- 约 1272 字
- 阅读
- 1 次
