如何安全地丢弃 golang 数据库/sql 池连接,例如当它们指向只读副本时?

我们一直在使用 golangdatabase/sqlgithub.com/lib/pqPostgreSQL 集群,这意味着作为复制主服务器的某个数据库服务器在先前的主服务器发生故障后可能是只读副本。

最近,我们的低使用率服务设法在其连接池中保留一个连接(没有会打开第二个连接的并发请求),并且其目标已降级为只读副本。结果,对服务的每个写入操作都失败,直到它重新启动。如果与集群建立了新连接,就不会发生这种情况。

问题是我找不到记录在案的方法来丢弃某些类型错误的连接。唯一database/sql听起来正确的公共方法是Conn.Close将连接返回到池而不关闭它。不调用它会导致资源泄漏,最终使池无法使用。有没有一种可持续的方法可以在应用程序需要时摆脱连接?


胡子哥哥
浏览 127回答 3
3回答

紫衣仙女

我相信在使用 时database/sql,答案是“否”,尽管我很乐意得到纠正。不久前,出于类似的原因(无法控制低级别的连接),我们从database/sqlwith切换lib/pq到纯 Go jackc/pgx ,并对结果感到满意。该模块提供了ConnPool.Reset听起来像你在这里想要的东西:Reset 关闭所有打开的连接,但让池保持打开状态。它旨在用于检测到会中断所有连接的错误(例如网络中断或服务器状态更改)。在签出连接时重置池是安全的。这些连接将在返回池时关闭。

aluckdog

最好的选择可能是 Postgres 的DISCONNECT命令。_, err := conn.ExecContext(context.Background(), "DISCONNECT")将导致连接从服务器端关闭。

一只斗牛犬

我认为您可以通过使用 Raw 函数并返回 driver.ErrBadConn 错误来丢弃它:conn.Raw(func(interface{}) error { return driver.ErrBadConn })
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go