buffalo 的 database.yml 不支持心跳配置,因其仅用于迁移和开发连接管理,不解析 testonborrow 等字段;真实保活需依赖 db.setconnmaxlifetime、dsn 超时参数(如 timeout=5s)及应用层重试机制。

Buffalo 的 database.yml 不支持心跳配置
Buffalo 自动生成的 database.yml 仅用于迁移和开发期连接管理,它本身不解析或传递任何连接池级的心跳参数(如 testOnBorrow、validationQuery 或 ping)。你往里面加字段不会生效,Go 的 database/sql 也不认这些 YAML 键。
真正起作用的是底层驱动(如 mysql 或 postgres)和 Go 标准库连接池的设置。Buffalo 没有封装心跳逻辑,必须手动干预初始化流程。
Go 原生方式:用 db.SetConnMaxLifetime + 空闲连接复用
Buffalo 底层用的是 Go 的 database/sql,它没有“主动 ping”的 API,但靠两个机制间接实现保活:
-
db.SetConnMaxLifetime(time.Minute * 30):让连接在池中存活不超过 30 分钟,到期后自动重建——这能规避 MySQL 默认wait_timeout=28800导致的假死 -
db.SetMaxIdleConns(5)和db.SetMaxOpenConns(20):保持一定数量空闲连接,提高被复用概率,减少新建开销 - 注意:
SetConnMaxLifetime只对归还池中的连接生效,事务中长期持有的连接不受影响
MySQL 驱动层加 timeout 和 readTimeout
如果你用的是 github.com/go-sql-driver/mysql,必须把超时参数拼进 DSN,否则网络中断或数据库重启后,连接会卡住不报错:
- 在
database.yml的url字段里追加:&timeout=5s&readTimeout=10s&writeTimeout=10s - 完整示例:
mysql://user:pass@127.0.0.1:3306/db?parseTime=true&timeout=5s&readTimeout=10s&writeTimeout=10s - 这些参数由驱动直接处理,
database/sql不介入;漏掉readTimeout容易导致查询挂起数分钟
需要真 ping?得自己写中间件或包装 sql.DB
Buffalo 没提供钩子拦截每次 db.Query 前执行 PING,所以没法像 ThinkPHP 那样配 'ping' => true。可行路径只有两个:
- 在 Buffalo 的
app.go初始化 DB 后,用 goroutine 定期调用db.Ping()(不推荐:可能干扰正常流量,且无法覆盖所有连接) - 封装一个带健康检查的
*sql.DB子类,在每次Query/Exec前先Ping,但要注意:MySQL 的PING是轻量请求,但频繁调用会增加 1–2ms RTT 开销 - 更务实的做法是:依赖
SetConnMaxLifetime+ DSN 超时 + 应用层重试(比如用github.com/avast/retry-go包捕获driver.ErrBadConn)
真实生产环境里,95% 的“连接断开”问题靠 max-lifetime 和 DSN 超时就能覆盖;硬加 ping 往往是过早优化,还容易掩盖连接泄露这类更严重的问题。











