# 25P03 — 事务中空闲会话超时（idle_in_transaction_session_timeout）

> PostgreSQL SQLSTATE 25P03：诊断并恢复开放事务中空闲会话被服务器终止的过程。
---

# 25P03 — 事务中空闲会话超时（idle_in_transaction_session_timeout）

## 速览 {#at-a-glance}

`25P03` 是终止会话的 FATAL 条件。当会话在开放事务中等待客户端下一条查询的时间超过有效 `idle_in_transaction_session_timeout` 时触发。选定案例使用 300 ms 作为测试触发值，不是生产建议。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `25P03` |
| 条件名 | `idle_in_transaction_session_timeout` |
| 状态 | `有效` |
| 已知存在于 | `9.6.0` |
| 锁定快照 | `9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT` |
| 别名 | `—` |

<!-- source facts: data/errcodes/25P03.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

该超时防止会话在等待客户端期间长期持有开放事务，从而持有锁并延迟清理。它作用于事务中的空闲等待，包括 `idle in transaction` 和 `idle in transaction (aborted)` 状态，不是正在执行的语句；`statement_timeout` 取消单条语句，而支持该设置的版本中 `transaction_timeout` 限制整个事务生命周期。选定运行只覆盖未中止的 `INTRANS` 路径。

## 诊断 {#diagnosis}

会话消失前，先在该目标会话自身检查有效的 `SHOW idle_in_transaction_session_timeout`（或对应的 `pg_settings` 行）。控制连接上的 `SHOW` 或 `pg_settings` 反映的是观察者后端，不能用来确认另一个会话实际通过 `SET` 得到的值。再从控制连接查看 `pg_stat_activity` 中 `pid`、`usename`、`application_name`、`client_addr`、`state`、`xact_start`、`state_change`、`query_start`、`query` 等字段，并筛选 `state IN ('idle in transaction', 'idle in transaction (aborted)')`。若状态已经中止，应把更早的根错误和 25P02 作为独立诊断保留；选定运行是未中止的 `INTRANS` 路径。这些字段可定位连接池或应用路径以及空闲时长，但观察者权限可能限制可见内容。再按 backend PID、SQLSTATE、`error_severity = FATAL` 和精确报文关联 FATAL 记录。选定的 psycopg/libpq 栈在驱动诊断和 CSV 日志中都暴露了 25P03；PG18 还提供 JSON 日志。原连接已关闭，不能在其上用 `ROLLBACK` 修复事务。

## 处理 {#response}

把原会话视为已消失：从连接池移除它，重连后再判断能否重试幂等工作。要避免再次发生，应在连接归还连接池前提交或回滚，并修复留下开放事务的应用路径。不要为了压制错误而降低该超时；更短的值会更容易触发终止。可把有效值设在合法空闲时长之上；只有部署明确接受锁和清理风险时才设为 `0`。服务器关闭该会话时会在退出前回滚开放且尚未完成的事务；死亡连接不能再接收 `ROLLBACK`。对已终止会话中已知未提交的事务，不能通过该连接恢复。若是另一种网络故障发生在客户端可能已发送 `COMMIT` 之后，应从新连接对账业务结果再重试；并非每个 25P03 FATAL 都意味着这种不确定性。

## FATAL 报文 {#messages}

服务器源码固定报出 `terminating connection due to idle-in-transaction timeout`，严重级别为 `FATAL`；原连接会被终止。

## 实测诊断 {#observed}

`18.6 (Homebrew) / latest`：FATAL SQLSTATE `25P03`；主报文 `terminating connection due to idle-in-transaction timeout`；backend PID `26447`；原连接已关闭 `True`；CSV 日志 `25P03`；JSON 日志 `25P03`；新连接探测 `1`。
`10.21 (Debian 10.21-1.pgdg90+1) / pg10`：FATAL SQLSTATE `25P03`；主报文 `terminating connection due to idle-in-transaction timeout`；backend PID `81`；原连接已关闭 `True`；CSV 日志 `25P03`；JSON 日志 `不适用`；新连接探测 `1`。

## 代表案例 {#case}

下列 SQL 片段不是一次性粘贴脚本：在测试连接上执行设置、PID 和 `BEGIN` 后停止发送查询，由独立观察连接或日志收集器等待 FATAL；原连接终止后，另开新连接执行最后的探测。运行器从共享语句清单（registry）读取这些语句，完整断言、日志收集器关联、环境和清理见 [案例导出](../../data/cases/25p03.json)。

<!-- BEGIN SQLSTATE SNIPPET: idle_in_transaction_timeout -->
```sql
-- set_timeout
SET idle_in_transaction_session_timeout = '300ms';
-- backend_pid
SELECT pg_backend_pid();
-- begin
BEGIN;
-- probe
SELECT 1;
```
<!-- END SQLSTATE SNIPPET -->

上述片段的 SQLSTATE、诊断、状态和修复断言来自共享语句清单（registry）（SHA-256 `95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2`）；[结构化证据](../../data/evidence/25p03.json)。

作者证据 ID：`identity`, `timeout-path`, `runtime`。选定运行记录：`runtime.25P03-batch2c-latest-20260909.latest`, `runtime.25P03-batch2c-pg10-20260909.pg10`。
## 版本与边界 {#versions}

选定的 300 ms 终止案例在 PostgreSQL 18.6 与 10.21 通过。PG18 按配置提供 CSV 和 JSON 日志记录；PG10 只有 CSV。两个目标的新连接都成功执行 `SELECT 1`。超时值取决于部署，本案例不规定生产值。

## 相关 {#related}

[25P04 事务超时](../25p04/)、[25006 只读 SQL 事务](../25006/)、[57014 查询取消](../57014/)。

## 来源 {#sources}

- [`src.errcodes.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt) (SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`)
- `src.calls.REL_18_6` — `raw/calls/REL_18_6.jsonl` (SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`)
- [`src.postgres.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L3473-L3501) (SHA-256 `9fb62275b1badf94d01ab351337b60410cd9b3ab1fe63fa9f23d6d2185a21061`)
- [`src.config.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/config.sgml#L10252-L10347) (SHA-256 `ffca322c15315ba670733d6b320f23cbba7374db0d18937298ffc07b58799ef6`) · [official documentation](https://www.postgresql.org/docs/18/runtime-config-client.html)
- [`doc.monitoring.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/monitoring.sgml#L706-L875) (SHA-256 `06b147f8d966fe46821871703ffcee8a3449cc3f7de5b64b9177f48569fe96f6`) · [官方监控文档](https://www.postgresql.org/docs/18/monitoring-stats.html)
- [`src.system_views.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/system_views.sql#L604-L605) (SHA-256 `418f4ae7472fe0742e6fbdc7a055581602c5131e082aa6f17e2c7269bf711972`) · [官方 `pg_settings` 文档](https://www.postgresql.org/docs/18/view-pg-settings.html)
- [`doc.protocol.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/protocol.sgml#L61-L65) (SHA-256 `745339e07ebbc2bb67d98b258e25772ada644ef26011e3cd6b3fcbb435235f89`) · [官方协议文档](https://www.postgresql.org/docs/18/protocol.html)
