↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

Wiki / SQLSTATE

25P03 — 事务中空闲会话超时(idle_in_transaction_session_timeout)

会话在开放事务中空闲超时,被服务器终止。

英文手册覆盖始于 PostgreSQL 8.1. 来源历史与运行验证各自保留独立版本边界。

当前阅读 PG 18·选择有来源记录的版本

aliases
未知
class name
Invalid Transaction State
condition name
idle_in_transaction_session_timeout
lang
en
sqlstate
25P03

版本定义 PG 18

25P03 — 事务中空闲会话超时(idle_in_transaction_session_timeout)

速览 {#at-a-glance}

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

含义 {#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)读取这些语句,完整断言、日志收集器关联、环境和清理见 案例导出。

-- set_timeout
SET idle_in_transaction_session_timeout = '300ms';
-- backend_pid
SELECT pg_backend_pid();
-- begin
BEGIN;
-- probe
SELECT 1;

上述片段的 SQLSTATE、诊断、状态和修复断言来自共享语句清单(registry)(SHA-256 95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2);结构化证据。

作者证据 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 事务超时、25006 只读 SQL 事务、57014 查询取消。

来源 {#sources}

比较版本

SQLSTATE 证据与已记录的运行版本

cases · idle_in_transaction_timeout
{
  "assertions": [
    "The original session is terminated by the timeout",
    "The collector records FATAL 25P03 for the matching backend PID",
    "A fresh connection can execute SELECT 1"
  ],
  "case_id": "idle_in_transaction_timeout",
  "cleanup": "Drop the case schema with an owner connection.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "A runner-owned disposable target is provisioned."
  ],
  "repair": "Use the state-specific recovery documented on the page; do not reuse a terminated connection.",
  "trigger": "Set idle_in_transaction_session_timeout, BEGIN, wait idle, and probe the terminated session.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity
{
  "claim_id": "identity",
  "limits": "The code is emitted at session termination severity FATAL in the selected path.",
  "method": "Read the fixed condition row and macro.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "25P03 is idle_in_transaction_session_timeout in Class 25."
}
claims · timeout-path
{
  "claim_id": "timeout-path",
  "limits": "The server terminates the connection; ROLLBACK cannot be sent through that dead session.",
  "method": "Trace the timeout interrupt and the fixed configuration documentation.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.postgres.18.6",
    "src.config.18.6",
    "src.calls.REL_18_6"
  ],
  "statement": "ProcessInterrupts emits FATAL 25P03 after the session has remained idle inside an open transaction longer than idle_in_transaction_session_timeout."
}
claims · runtime
{
  "claim_id": "runtime",
  "limits": "The selected timeout is 300 ms in a runner-owned disposable target; production timeout policy is deployment-specific.",
  "method": "Match collector records by PID, SQLSTATE, and message, then probe a fresh connection.",
  "position": 2,
  "runtime": [],
  "sources": [
    "runtime",
    "runtime.25P03-batch2c-latest-20260909.latest",
    "runtime.25P03-batch2c-pg10-20260909.pg10"
  ],
  "statement": "Both selected targets received FATAL 25P03 for the exact backend PID, and a fresh owner connection successfully ran SELECT 1 after termination."
}
claims · diagnosis-observer-boundary
{
  "claim_id": "diagnosis-observer-boundary",
  "limits": "Visibility of pg_stat_activity fields depends on observer privileges; the selected runtime records establish PID/log correlation, not universal monitoring permissions.",
  "method": "Read the fixed monitoring view documentation and system-view definition before writing the observer/session diagnostic split.",
  "position": 3,
  "runtime": [],
  "sources": [
    "doc.monitoring.18.6",
    "src.system_views.18.6"
  ],
  "statement": "The fixed monitoring documentation defines pg_stat_activity as one row per server process with current activity, including xact_start and state_change; pg_settings is defined over pg_show_all_settings for the current backend. Capture timeout settings on the timed session itself, because SHOW or pg_settings on an observer connection cannot establish another backend's effective SET value."
}
claims · state-scope
{
  "claim_id": "state-scope",
  "limits": "No aborted-transaction timeout was run in this batch; preserve any earlier root error and 25P02 separately when diagnosing that state.",
  "method": "Read the fixed pg_stat_activity state definitions alongside the timeout GUC description and compare them with the selected runtime status.",
  "position": 4,
  "runtime": [],
  "sources": [
    "doc.monitoring.18.6",
    "src.config.18.6"
  ],
  "statement": "The fixed monitoring view distinguishes idle in transaction from idle in transaction (aborted); the timeout documentation's open-transaction scope covers idle waiting, while the selected runtime demonstrates only the non-aborted INTRANS path."
}
claims · termination-rollback
{
  "claim_id": "termination-rollback",
  "limits": "This establishes server-side rollback on forced connection close; it does not resolve a separate network failure after a client may have sent COMMIT.",
  "method": "Read the fixed protocol session-termination rule and align the recovery prose with the FATAL path.",
  "position": 5,
  "runtime": [],
  "sources": [
    "doc.protocol.18.6"
  ],
  "statement": "The fixed protocol documentation states that when the backend closes a connection it rolls back any open incomplete transaction before exiting; the driver cannot send a later ROLLBACK on that closed session."
}
messages · fatal
{
  "limits": "This is a static FATAL message; the driver may expose or omit SQLSTATE depending on client stack.",
  "message_id": "fatal",
  "path": "",
  "position": 0,
  "raw": {
    "id": "fatal",
    "limits": "This is a static FATAL message; the driver may expose or omit SQLSTATE depending on client stack.",
    "primary_template": "terminating connection due to idle-in-transaction timeout",
    "severity_source": "FATAL",
    "sources": [
      "src.postgres.18.6"
    ],
    "sqlstate": "25P03"
  },
  "severity": "FATAL",
  "sources": [
    "src.postgres.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "terminating connection due to idle-in-transaction timeout",
      "position": 0,
      "role": "",
      "template": "terminating connection due to idle-in-transaction timeout"
    }
  ]
}
runtimes · runtime.25P03-batch2c-latest-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "idle_in_transaction_timeout"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25P03/cases.json",
      "sha256": "e6c8d08f3b964c308d1a2c87f64919aa7d914db438456658afa230383c7f27eb"
    },
    "case_status": "passed",
    "cases": [
      "idle_in_transaction_timeout"
    ],
    "id": "runtime.25P03-batch2c-latest-20260909.latest",
    "observed": {
      "backend_pid": 26447,
      "collector_csv_error_severity": "FATAL",
      "collector_csv_sqlstate": "25P03",
      "collector_json_error_severity": "FATAL",
      "collector_json_sqlstate": "25P03",
      "fresh_connection_probe": 1,
      "fresh_connection_status": "IDLE",
      "original_connection_closed": true,
      "primary": "terminating connection due to idle-in-transaction timeout",
      "recovery_requires_new_connection": true,
      "severity": "FATAL",
      "sqlstate": "25P03",
      "status_before_timeout": "INTRANS"
    },
    "raw": "verify/results/25P03-batch2c-latest-20260909/latest/raw.jsonl",
    "raw_sha256": "eeb467a1908730a03d6eb9cf1e1319a5d658dcb4a0bb42d0907f8045682778bf",
    "run_id": "25P03-batch2c-latest-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/25P03/snippets.json",
      "sha256": "95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2"
    },
    "status": "passed",
    "summary": "verify/results/25P03-batch2c-latest-20260909/latest/summary.json",
    "summary_sha256": "ec210989486eb92bda87e874942b5987d23f121f914c780e30851f3fe04e9379",
    "target": "latest",
    "target_status": "passed"
  },
  "run_id": "25P03-batch2c-latest-20260909",
  "runtime_id": "runtime.25P03-batch2c-latest-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.25P03-batch2c-pg10-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "idle_in_transaction_timeout"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25P03/cases.json",
      "sha256": "e6c8d08f3b964c308d1a2c87f64919aa7d914db438456658afa230383c7f27eb"
    },
    "case_status": "passed",
    "cases": [
      "idle_in_transaction_timeout"
    ],
    "id": "runtime.25P03-batch2c-pg10-20260909.pg10",
    "observed": {
      "backend_pid": 81,
      "collector_csv_error_severity": "FATAL",
      "collector_csv_sqlstate": "25P03",
      "collector_json_error_severity": null,
      "collector_json_sqlstate": null,
      "fresh_connection_probe": 1,
      "fresh_connection_status": "IDLE",
      "original_connection_closed": true,
      "primary": "terminating connection due to idle-in-transaction timeout",
      "recovery_requires_new_connection": true,
      "severity": "FATAL",
      "sqlstate": "25P03",
      "status_before_timeout": "INTRANS"
    },
    "raw": "verify/results/25P03-batch2c-pg10-20260909/pg10/raw.jsonl",
    "raw_sha256": "cc716ef184879dac6e0e6885922e940faa0bfed5ef22ef64e479403db499c7e8",
    "run_id": "25P03-batch2c-pg10-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/25P03/snippets.json",
      "sha256": "95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2"
    },
    "status": "passed",
    "summary": "verify/results/25P03-batch2c-pg10-20260909/pg10/summary.json",
    "summary_sha256": "a76cbc2408369f7baca614ed533cba18d8b7f105d7fd3319107be5c01143917d",
    "target": "pg10",
    "target_status": "passed"
  },
  "run_id": "25P03-batch2c-pg10-20260909",
  "runtime_id": "runtime.25P03-batch2c-pg10-20260909.pg10",
  "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
  "status": "passed",
  "target": "pg10"
}
sources · src.errcodes.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/errcodes.txt",
  "position": 0,
  "sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
  "source_id": "src.errcodes.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt"
}
sources · src.calls.REL_18_6
{
  "commit": "",
  "docs_url": "",
  "kind": "local_artifact",
  "location": "",
  "path": "raw/calls/REL_18_6.jsonl",
  "position": 1,
  "sha256": "9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf",
  "source_id": "src.calls.REL_18_6",
  "tag": "",
  "url": ""
}
sources · src.postgres.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/tcop/postgres.c",
  "position": 2,
  "sha256": "9fb62275b1badf94d01ab351337b60410cd9b3ab1fe63fa9f23d6d2185a21061",
  "source_id": "src.postgres.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L3473-L3501"
}
sources · src.config.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/runtime-config-client.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/config.sgml",
  "position": 3,
  "sha256": "ffca322c15315ba670733d6b320f23cbba7374db0d18937298ffc07b58799ef6",
  "source_id": "src.config.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/config.sgml#L10252-L10347"
}
sources · doc.monitoring.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/monitoring-stats.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/monitoring.sgml",
  "position": 4,
  "sha256": "06b147f8d966fe46821871703ffcee8a3449cc3f7de5b64b9177f48569fe96f6",
  "source_id": "doc.monitoring.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/monitoring.sgml#L706-L875"
}
sources · src.system_views.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/view-pg-settings.html",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/catalog/system_views.sql",
  "position": 5,
  "sha256": "418f4ae7472fe0742e6fbdc7a055581602c5131e082aa6f17e2c7269bf711972",
  "source_id": "src.system_views.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/system_views.sql#L604-L605"
}
sources · doc.protocol.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/protocol.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/protocol.sgml",
  "position": 6,
  "sha256": "745339e07ebbc2bb67d98b258e25772ada644ef26011e3cd6b3fcbb435235f89",
  "source_id": "doc.protocol.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/protocol.sgml#L61-L65"
}

来源引用

完整定义与证据 JSON

定义来源

center · PostgreSQL 18 · english-manuals:1db52d3da9a813f5a4ad9099aae2dc662e759b68aa365475726e0f99ee98adc1

正文语言: zh-Hans · english-manuals:1db52d3da9a813f5a4ad9099aae2dc662e759b68aa365475726e0f99ee98adc1