根本原因是buffalo db命令不读database.yml,只认DB_URL环境变量或models.NewDB()硬编码配置;SQLite因pop v6+移除支持而完全不可用;且必须先buffalo db create建库再migrate,顺序不可颠倒。

buffalo db migrate 为什么总是报错或静默失败
根本原因不是命令写错,而是 Buffalo 的 buffalo db 命令根本不读 database.yml,它只认环境变量(如 DB_URL)或 models/NewDB() 里的硬编码配置。你改了 YAML 文件却没改 Go 代码,迁移必然连不上库。
常见错误现象包括:unknown dialect 'sqlite3'(pop v6+ 已移除 SQLite 支持)、connection refused(PostgreSQL 缺 sslmode=disable)、invalid connection(MySQL 没加 parseTime=true)。
- 检查
models/database.go中NewDB()返回的连接是否正确——这是唯一生效的配置源 - 临时用
DB_URL=postgres://localhost:5432/myapp?sslmode=disable buffalo db migrate up覆盖配置,快速验证连通性 - SQLite 用户请放弃
buffalo db:它在 pop v6+ 中完全不可用,连buffalo db create都会 panic
执行迁移前必须先建库:buffalo db create 不是可选步骤
buffalo db create 和 buffalo db migrate 是两个独立动作,且顺序不可颠倒。前者创建数据库(schema-level),后者才建表(table-level)。跳过 create 直接 migrate,会报 database "myapp" does not exist 或静默卡住。
- PostgreSQL:确保
postgres系统库可连,且当前用户有CREATEDB权限 - MySQL:root 用户需有
CREATE DATABASE权限;非 root 用户要提前手动CREATE DATABASE myapp - SQL Server:不支持本地文件路径,
host必须是 IP 或域名,不能是localhost(某些驱动解析异常)
buffalo db migrate up/down/rollback 的实际行为差异
buffalo db migrate 默认操作的是 models/migrations/ 下所有未执行的 up 迁移;但 down 和 rollback 行为不同:down 执行最新一个 migration 的 Down() 函数,rollback 则回退到指定版本(如 rollback 202411051030)。
- 迁移文件名中的时间戳是版本号,
rollback必须精确匹配(如202411051030,不能少位) -
up不会重复执行已记录在schema_migrations表里的迁移,但down不校验该记录是否存在,直接执行函数体 - 测试环境跑
TestMain时若没清空schema_migrations表,后续go test会因“migration already applied”失败
如何安全地在 CI 或测试中自动跑迁移
CI 环境里不能依赖交互式命令,得用 Go 代码控制迁移流程。关键点是:连接对象必须复用、迁移方向要显式传参、失败必须中断构建。
- 用
pop.Connect("test")获取连接,别用app.Pop()(测试时 app 尚未初始化) - 调
migrate.Up(tx, "test")或migrate.Down(tx, "test", 1),第二个参数是环境名,对应database.yml的 key(但注意:这里仍只是用来取 dialect,真正连接靠pop.Connect返回的实例) - 迁移前加
tx.RawQuery("DROP TABLE IF EXISTS schema_migrations").Exec()清理残留,避免测试间干扰
最易被忽略的是:迁移脚本里的 RawQuery().Exec() 是 DDL 操作,在 MySQL 上可能锁表,在 PostgreSQL 上对大表建索引会阻塞写入——线上迁移务必单独评估窗口期。


















