简体   繁体   中英

How to safely discard golang database/sql pooled connections, for example when they point to a read-only replica?

We have been using golang's database/sql and github.com/lib/pq with a PostgreSQL cluster, meaning that a certain database server that was a replication master might be a read-only replica after the previous master has failed.

Recently, our low-usage service managed to keep a single connection in its connection pool (there were no concurrent requests that would have opened a second connection), and its target had been demoted to a read-only replica. As a result, each write operation to the service failed until it was restarted. That would not have happened, if a new connection was made to the cluster.

The problem is I can't find a documented way to discard a connection on certain kinds of errors. The only public method in database/sql that sounds correct is Conn.Close which returns the connection to the pool without closing it. Not calling it will cause a resource leak which will eventually make the pool unusable. Is there a sustainable way to get rid of a connection when the application wants to?

I believe that when using database/sql , the answer is "no", though I'd be happy to be corrected.

A while back, we switched from database/sql with lib/pq to the pure Go jackc/pgx for similar reasons (the inability to control connections on a low level), and were happy with the result. That module offers ConnPool.Reset which sounds like what you want here:

Reset closes all open connections, but leaves the pool open. It is intended for use when an error is detected that would disrupt all connections (such as a network interruption or a server state change).

It is safe to reset a pool while connections are checked out. Those connections will be closed when they are returned to the pool.

Your best bet is probably Postgres's DISCONNECT command.

_, err := conn.ExecContext(context.Background(), "DISCONNECT")

will cause the connection to be closed, from the server side.

我认为您可以通过使用 Raw 函数并返回 driver.ErrBadConn 错误来丢弃它:

conn.Raw(func(interface{}) error { return driver.ErrBadConn })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM