

# PostgreSQL 中的失效连接处理
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling"></a>

当客户端应用程序已放弃或异常终止，但数据库会话在服务器上仍保持活动状态时，就会出现失效连接。当客户端进程崩溃或意外终止，但没有正确地关闭其数据库连接或取消正在进行的请求时，通常会出现这种情况。

当服务器进程处于空闲状态或试图向客户端发送数据时，PostgreSQL 可以高效地识别和清理失效连接。但是，对于处于空闲状态、等待客户端输入或当前正在运行查询的会话，检测过程颇具挑战性。为了处理这些情况，PostgreSQL 提供了 `tcp_keepalives_*`、`tcp_user_timeout` 和 `client_connection_check_interval` 参数。

**Topics**
+ [了解 TCP keepalive](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding)
+ [Aurora PostgreSQL 中的关键 TCP keepalive 参数](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Parameters)
+ [TCP keepalive 设置的使用案例](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases)
+ [最佳实践](#Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices)

## 了解 TCP keepalive
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Understanding"></a>

TCP Keepalive 是一种协议级机制，有助于保持和验证连接完整性。每个 TCP 连接都保持内核级别的设置，这些设置控制着 keepalive 行为。当 keepalive 计时器到期时，系统会执行以下操作：
+ 发送一个没有数据且设置了 ACK 标志的探测数据包。
+ 根据 TCP/IP 规范，期待来自远程端点的响应。
+ 根据响应或无响应来管理连接状态。

## Aurora PostgreSQL 中的关键 TCP keepalive 参数
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.Parameters"></a>


| 参数 | 说明 | 默认值 | 
| --- |--- |--- |
| tcp\$1keepalives\$1idle | Specifies number of seconds of inactivity before sending keepalive message. | 300 | 
| tcp\$1keepalives\$1interval | Specifies number of seconds between retransmissions of unacknowledged keepalive messages. | 30 | 
| tcp\$1keepalives\$1count | Maximum lost keepalive messages before declaring connection dead | 2 | 
| tcp\$1user\$1timeout | Specifies how long (in Milliseconds) unacknowledged data can remain before forcibly closing the connection. | 0 | 
| client\$1connection\$1check\$1interval | Sets the interval (in Milliseconds) for checking client connection status during long-running queries. This ensures quicker detection of closed connections. | 0 | 

## TCP keepalive 设置的使用案例
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases"></a>

### 使空闲会话保持连接状态
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.KeepingAlive"></a>

为防止空闲连接因处于非活动状态而被防火墙或路由器终止：
+ 配置 `tcp_keepalives_idle` 定期发送 keepalive 数据包。

### 检测失效连接
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.UseCases.DetectingDead"></a>

要迅速检测失效连接：
+ 调整 `tcp_keepalives_idle`、`tcp_keepalives_interval` 和 `tcp_keepalives_count`。例如，使用 Aurora PostgreSQL 默认值，检测到失效连接大约需要一分钟（2 次探测 × 30 秒）。降低这些值可以加快检测速度。
+ 使用 `tcp_user_timeout` 来指定等待确认的最长时间。

TCP keepalive 设置有助于内核检测失效连接，但在使用套接字之前，PostgreSQL 可能无法执行操作。如果会话正在运行长时间的查询，则可能只有在查询完成后才能检测到失效连接。在 PostgreSQL 14 及更高版本中，`client_connection_check_interval` 可以通过在查询执行期间定期轮询套接字来加快失效连接检测。

## 最佳实践
<a name="Appendix.PostgreSQL.CommonDBATasks.DeadConnectionHandling.BestPractices"></a>
+ **设置合理的 keepalive 间隔：**调整 `tcp_user_timeout`、`tcp_keepalives_idle`、`tcp_keepalives_count` 和 `tcp_keepalives_interval`，以平衡检测速度与资源用量。
+ **针对环境进行优化：**使设置与网络行为、防火墙策略和会话需求相一致。
+ **利用 PostgreSQL 功能**：在 PostgreSQL 14 及更高版本中使用 `client_connection_check_interval` 来进行高效的连接检查。