Postgres libpq 如何判断连接是否已终止

Postgres libpq how to tell if a connection has been terminated

给定以下 libpq 代码:

PGconn * internalConnection = PQconnectdb("my connection string");
if (PQstatus(internalConnection) != CONNECTION_OK)
{
   // return error on failure
}

// Kill all connections
if(0 == PQsendQuery(internalConnection, "SELECT pid, (SELECT pg_terminate_backend(pid)) as killed from pg_stat_activity"))
{
   // return error on failure
}

执行以下操作:

  1. 连接到服务器。
  2. 执行查询,终止所有连接(包括此连接)。

我如何通过客户端得知连接已终止?如果我再次 运行 以下内容:

PQstatus(internalConnection)

我的结果仍然是 CONNECTION_OK

使用 MySQL API 我可以在连接上检查 mysql_ping 以查看连接是否仍然打开,但是在 Postgres 上,似乎没有类似的方法打电话(我能找到)。

关于如何从客户端确定连接是否已终止,有什么建议吗?

要通过 libpq 查看连接是否有效,您可以发送空查询字符串:

res = PQexec(conn, "");

并测试结果。

在 PostgreSQL 协议级别,可以使用简单的 Sync 消息更有效地完成此操作,但 libpq 目前没有提供仅发送 Sync 的方法。


不过你不应该那样做。当服务器关闭连接时,它会向客户端发送一个 TCP RST。这应该通知客户端其套接字已关闭。虽然我没有测试过,但我怀疑调用 PQconsumeInput 足以处理连接上的任何剩余数据并注意到套接字已关闭。但是请注意,如果没有要使用的输入,那么此函数将阻止等待来自服务器的消息。


顺便说一句,虽然在这种情况下测试连接是合理的(大概),但通常这是一个非常糟糕的设计。你永远不应该这样做:

  • 测试连接
  • 运行查询
  • 假设成功

因为测试连接和实际执行一个或多个查询之间存在竞争。更不用说查询可能因其他原因而失败。

您的应用程序应该始终能够处理失败的交易,并且能够重试。你应该有适当的逻辑来中止并重试暂时性错误的交易,或者如果连接本身是坏的则重新连接。

PostgreSQL 的 libpq 可以使这比目前对用户更容易。它应该公开一些函数来测试 SQLState 以查看它是否可能是瞬态的,例如,这样应用程序就可以使用单个调用来重试死锁中止、序列化失败等。现在你必须自己做。