buffalo 的 pop orm 连接池参数必须通过代码显式设置,database.yml 中的 maxidle、minidle 等无效;需在 app.go 或 models.go 中调用 pop.newconnection() 后,立即设置 setmaxopenconns、setmaxidleconns 和 setconnmaxlifetime(须略小于数据库 wait_timeout),否则压测时连接不收敛、出现 i/o timeout 或 invalid connection。

Buffalo 默认用 pop 作为 ORM,但它的 database.yml 不暴露连接池核心参数,直接改 YAML 文件无法生效——因为 pop 在初始化时会忽略大部分标准连接池配置项,比如 maxIdle、minIdle、maxOpen 等,只认少数几个(如 max_open_connections),且行为与预期不一致。
pop.Connection 初始化时必须手动覆盖连接池参数
Buffalo 的 pop.Connect() 返回的 *pop.Connection 内部封装了 *sql.DB,但默认调用的是 pop 自己的 newConnection(),它不会读取 database.yml 里的池相关字段。你得在 app.go 或 models/models.go 中显式设置:
- 调用
pop.NewConnection()后,立即对connection.DB.SetMaxOpenConns()、.SetMaxIdleConns()、.SetConnMaxLifetime()赋值 - 不要依赖
buffalo db migrate自动加载的连接——它用的是临时连接,不复用你配好的池 - 若用了多环境(dev/staging/prod),每个环境的
connection实例都得单独设一遍
MySQL 驱动 URL 中的 poolSize 参数无效
像 mysql://user:pass@localhost:3306/db?poolSize=20 这种写法对 pop 完全没用。MySQL Go 驱动(go-sql-driver/mysql)本身不解析 poolSize,那是 Java JDBC 的参数名。pop 也不做转换。真正起作用的只有:
-
parseTime=true(影响 time.Time 解析) -
loc=UTC(时区,避免时间错乱) -
timeout/readTimeout/writeTimeout(底层 net.Conn 层级,非连接池)
连接池大小控制必须走 *sql.DB 接口,不能靠 DSN 字符串。
并发压测时连接数不收敛?检查 SetConnMaxLifetime
MySQL 默认 wait_timeout 是 28800 秒(8 小时),但生产环境常设为 300–600 秒。如果没调 connection.DB.SetConnMaxLifetime(5 * time.Minute),连接池会持续复用已超时的连接,导致 invalid connection 或卡死。常见现象:
- 压测初期正常,10 分钟后错误率陡增
- 日志里反复出现
ERROR #08006 read tcp: i/o timeout -
show processlist显示大量 Sleep 状态连接未释放
务必把 SetConnMaxLifetime 设为略小于数据库侧的 wait_timeout,并配合 SetMaxIdleConns(5) 防止空闲连接堆积。
真正生效的连接池配置不在 YAML 里,而在你亲手调的那几行 SetXXX 方法中;漏掉 SetConnMaxLifetime 是线上最隐蔽的连接泄漏源。











