跳转到主要内容

25P04 — 事务超时(transaction_timeout)

PostgreSQL SQLSTATE 25P04:显式或隐式事务超过 transaction_timeout 后终止会话。

25P04 — 事务超时(transaction_timeout)

速览

25P04transaction_timeout 触发的 FATAL 条件,覆盖显式 BEGIN 事务和由单条语句隐式启动的事务。选定的 18.6 案例使用 300 ms;PG10 因设置不可用而在源码/版本预检阶段跳过,不会探测未知设置。另有 PG16.15/PG17.11 的版本边界对照:PG16 返回设置不可用的 42704,PG17 实际产生 FATAL 25P04;该对照独立于选定基础案例。

字段
SQLSTATE 25P04
条件名 transaction_timeout
状态 有效
已知存在于 17.0
锁定快照 17.11, 18.6, 19beta3
ERRCODE_TRANSACTION_TIMEOUT
别名

含义

transaction_timeout 限制显式或隐式事务的存活时间,包括事务打开期间执行或等待的时间。触发后 PostgreSQL 发出 terminating connection due to transaction timeout 并终止会话。它不同于只中止一条语句的 statement_timeout,也不同于只覆盖客户端在开放事务中空闲时间的 idle_in_transaction_session_timeout。若 transaction_timeout 小于或等于其中任一设置,较长的超时会被忽略;预备事务不受此设置约束。

诊断

在支持该设置的服务器上,先在目标会话自身检查有效的 SHOW transaction_timeoutSHOW statement_timeoutSHOW idle_in_transaction_session_timeout。控制连接上的 SHOWpg_settings 反映的是观察者后端,不能用来确认另一个会话实际通过 SET 得到的值。再从控制连接查看 pg_stat_activitypidapplication_namestatexact_startstate_changequery_startquery 等字段,定位所属应用或连接池,并判断事务是在执行还是空闲。按 backend PID、SQLSTATE 25P04、error_severity = FATAL 和精确报文匹配日志收集器记录。选定的 18.6 运行中驱动也暴露了 25P04,原连接已关闭;新的连接成功执行 SELECT 1。PG10 在发送 SET transaction_timeout 之前就由最低版本预检跳过。

处理

丢弃已终止的会话并重连。对合法的长事务,可缩短工作、拆分工作单元或提高有效超时以控制在预算内;不要为了掩盖错误而降低超时。只有部署明确接受取消该保护时才设为 0。服务器关闭终止的会话时会在退出前回滚开放且尚未完成的事务;死亡连接不能再接收 ROLLBACK。已知尚未在该会话上提交的事务,不能通过该连接恢复。若另一种网络故障使客户端无法确定 COMMIT 是否到达服务器,应从新连接对账业务结果再重试;选定案例没有发送提交,不能据此声称存在这种不确定性。本批 PG10 没有兼容设置。

FATAL 报文

服务器源码固定报出 terminating connection due to transaction timeout,严重级别为 FATAL;原连接会被终止。

实测诊断

18.6 (Homebrew) / latest:FATAL SQLSTATE 25P04;主报文 terminating connection due to transaction timeout;backend PID 30576;原连接已关闭 True;CSV 日志 25P04;JSON 日志 25P04;新连接探测 110.21 (Debian 10.21-1.pgdg90+1) / pg10:案例 not_applicable(最低版本预检;未探测该目标不支持的设置)。

单独的边界对照:16.15 / pg16 因设置不可用返回 42704 并保持 IDLE,因此不计作 25P04 覆盖;17.11 / pg17 在 300 ms 后由 PID 73 产生 FATAL 25P04,CSV 与 JSON 都记录 FATAL 25P04,原连接关闭,新连接为 IDLE。这些记录不计入选定基础案例。

代表案例

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

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

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

作者证据 ID:identitytimeout-pathruntimeruntime.version-boundary。选定基础运行记录:runtime.25P04-batch2c-latest-20260909.latest。单独的边界记录:runtime.25P04-boundary-pg16-20260909.pg16runtime.25P04-boundary-pg17-20260909.pg17

单独的边界对照已经记录了可用性结果:PG16 返回 42704,PG17 继续并实际产生 FATAL 25P04。这个边界块是分支说明,不能整块一次性粘贴执行。在 PG16 上先执行 SHOW transaction_timeout;得到预期的 42704 后,如需证明连接仍健康,应在同一连接执行 SELECT 1,然后停止,跳过 SET transaction_timeoutBEGIN 和等待超时。在 PG17 或更高版本上,只有 SHOW 成功后才在目标连接执行 SET transaction_timeout、记录 PID 并执行 BEGIN;随后停止发送查询,由观察连接或日志收集器等待旧连接出现 FATAL 并关闭,最后只在新连接上执行探测。这些边界记录用于诊断对照,不增加选定基础案例数量。

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

版本与边界

锁定目录首次观察到 transaction_timeout 为 17.0。选定的 18.6 案例以 CSV/JSON 日志收集证据和新连接探测通过。单独的 PG17.11 边界案例实际记录了 FATAL 25P04,PG16.15 则记录设置不可用的 42704;两者都不替代选定基础运行。PG10 是真实的 not_applicable 最低版本预检跳过:handler 不会发送或探测未知设置,因此这不构成更早版本边界证据。

25P03 事务中空闲超时40001 可串行化失败57014 查询取消

来源