选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 错误代码 / Class 25 事务状态无效

25001 active_sql_transaction

活动 SQL 事务

ERROR 已实测 详解 实测通过

类别
Class 25 事务状态无效
严重等级
ERROR
条件名
active_sql_transaction
宏名称
ERRCODE_ACTIVE_SQL_TRANSACTION
启用版本
7.4
状态
活跃

版本覆盖

速览

25001 表示当前活动 SQL 事务违反了命令要求的事务边界。本案例在 BEGIN 后执行 VACUUM,得到精确错误;回滚后在事务块外执行 VACUUM 成功且连接保持 IDLE

含义

该码覆盖多条路径:PreventInTransactionBlock 会拒绝事务块、子事务或函数中的禁用 utility,源码分别格式化为 %s cannot run inside a transaction block%s cannot run inside a subtransaction%s cannot be executed from a function。其他路径会拒绝写入后的逻辑复制槽、子事务中的快照导出,或查询开始后的导入快照设置。在已经活动的事务中再次 BEGIN 是独立的 WARNING,因此严重级别和恢复方式取决于具体源码路径。

诊断

记录 SQLSTATE、严重级别、主报文、事务状态和命令。本案例的 VACUUM ERROR 后显式会话进入 INERROR,只有 ROLLBACK 恢复 IDLE。函数或子事务报错时,应先结束该上下文,再把命令作为位于任何显式事务块之外的一条独立顶层 utility 命令发出(例如驱动自动提交的单条命令);在同一 wrapper 内重试仍不满足 PreventInTransactionBlock。逻辑复制槽和快照报错则要检查是否已有写入、子事务或查询;“事务已在进行中”的 WARNING 不是 VACUUM 的 ERROR,本身不要求回滚。随后选定修复在事务块外执行 VACUUM,并断言成功和 IDLE

处理

禁用 utility 若位于不合适的事务块、函数或子事务中,应移到位于任何显式事务块之外的一条独立顶层命令(通常在自动提交连接上执行);不要把“顶层”理解为另一个 BEGIN。显式事务中的 ERROR 后先执行 ROLLBACK,再执行该命令。逻辑复制槽必须在此前没有写入的事务中创建;快照导出不能位于子事务,SET TRANSACTION SNAPSHOT 必须早于任何查询。重复 BEGINWARNING 应保留已有事务,不要仅因警告就回滚。应按精确源码路径处理,不能机械套用 VACUUM 修复。

可复现案例

在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。

vacuum_inside_transaction PG 10 / 18 有 SQL

前置条件

  • A disposable table exists
  • VACUUM is issued after an explicit BEGIN

触发

Run VACUUM inside an explicit transaction block.

断言

  • SQLSTATE is 25001
  • The transaction enters INERROR and rollback restores IDLE
  • The same connection can execute a follow-up query
  • VACUUM succeeds after rollback outside the transaction block

处置

Run transaction-control-restricted utility commands outside the transaction block; rollback the failed transaction before reuse.

清理

Drop the case schema with an owner connection.

实测诊断

18.6 (Homebrew) / latest:SQLSTATE 25001;primary VACUUM cannot run inside a transaction block;after_error INERROR;after_rollback IDLE;status_after_vacuum IDLE10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 25001;primary VACUUM cannot run inside a transaction block;after_error INERROR;after_rollback IDLE;status_after_vacuum IDLE

报文模板

源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。

主消息 %s cannot run inside a transaction block

来源:src/backend/access/transam/xact.c @ REL_18_6

适用范围:The %s substitution is the command name; this is one ERROR path for 25001.

主消息 %s cannot run inside a subtransaction

来源:src/backend/access/transam/xact.c @ REL_18_6

适用范围:The format string is source-backed; substitutions are supplied by the executing path.

主消息 there is already a transaction in progress

来源:src/backend/access/transam/xact.c @ REL_18_6

适用范围:This source path is explicitly WARNING and must not be presented as the VACUUM ERROR template.

主消息 %s cannot be executed from a function

来源:src/backend/access/transam/xact.c @ REL_18_6

适用范围:The %s substitution is the command name; this branch is rejected because it is called from a function.

主消息 cannot create logical replication slot in transaction that has performed writes

来源:src/backend/replication/logical/logical.c @ REL_18_6

适用范围:The source condition is a transaction that already has a top-level transaction ID from writes.

主消息 cannot export a snapshot from a subtransaction

来源:src/backend/utils/time/snapmgr.c @ REL_18_6

适用范围:The branch rejects export from the current subtransaction; prior committed subtransactions are handled separately by the source.

主消息 SET TRANSACTION SNAPSHOT must be called before any query

来源:src/backend/utils/time/snapmgr.c @ REL_18_6

适用范围:The command must be at the top level of a fresh transaction before a query establishes the snapshot.

源码报文模板

选定的 VACUUM 运行没有覆盖以下源码分支:

  • ERROR %s cannot run inside a subtransaction%s 替换为命令名)。
  • ERROR %s cannot be executed from a function%s 替换为命令名)。
  • ERROR cannot create logical replication slot in transaction that has performed writes
  • ERROR cannot export a snapshot from a subtransaction
  • ERROR SET TRANSACTION SNAPSHOT must be called before any query
  • WARNING there is already a transaction in progress

这些是源码证据,不是本案例新增的运行结论。

代表案例

本例中,VACUUM 在显式 BEGIN 块内被拒绝;ROLLBACK 后,同一 utility 作为事务块外的独立命令成功。完整 setup、断言与清理见案例导出

-- create
CREATE TABLE items(id integer PRIMARY KEY, note text NOT NULL);
-- seed
INSERT INTO items VALUES (1, 'seed');
-- begin
BEGIN;
-- trigger
VACUUM items;
-- rollback
ROLLBACK;
-- followup
SELECT 1 AS usable;
-- repair
VACUUM items;

本案例对应的 SQLSTATE、诊断、事务状态和修复断言均来自经核对的案例 registry;见结构化证据案例导出

作者证据 ID:identity, utility-path, other-paths, runtime。选定运行记录:runtime.25001-batch1-latest2-20260909.latest, runtime.25001-batch1-pg10b-20260909.pg10

版本与边界

锁定目录在 7.4 已观察到该条件,并在列出的正式快照中均存在。选定的 VACUUM 案例在 18.6 与 10.21 通过,包含回滚恢复和事务块外成功修复;其他 25001 路径仅有源码证据。

来源

证据

断言

每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。

  • 25001 is active_sql_transaction in Class 25.

    核实方式Read the fixed condition row and macro.

    不覆盖The code covers several operations that require a transaction boundary, including subtransactions and function execution.

    来源src/backend/utils/errcodes.txt

  • A utility such as VACUUM cannot run inside an explicit transaction block; xact.c formats the statement name into the 25001 primary message.

    核实方式Trace PreventInTransactionBlock and the VACUUM transaction restriction.

    不覆盖Some commands are allowed inside transactions; inspect the command-specific contract rather than retrying blindly.

    来源src/backend/access/transam/xact.c · doc/src/sgml/ref/vacuum.sgml · raw/calls/REL_18_6.jsonl

  • The same SQLSTATE has distinct source templates for subtransactions, function execution, logical replication slots after writes, and snapshot operations; a WARNING “there is already a transaction in progress” is a separate severity path.

    核实方式Read all fixed 25001 report groups selected by the source call scan.

    不覆盖Severity and recovery depend on the exact path; do not treat every 25001 as an ERROR.

    来源src/backend/access/transam/xact.c · raw/calls/REL_18_6.jsonl · src/backend/replication/logical/logical.c · src/backend/utils/time/snapmgr.c · src/backend/utils/time/snapmgr.c

  • The selected VACUUM case returned 25001 on PG18.6 and PG10.21, entered INERROR, recovered after ROLLBACK, accepted a follow-up query, and then completed VACUUM outside the transaction block with the connection IDLE.

    核实方式Read the selected summaries and raw diagnostics.

    不覆盖The case covers VACUUM in a transaction, not logical replication slots, snapshot export, function calls, or warning handling.

运行记录

目标服务器版本结果覆盖案例
latest 18.6 (Homebrew) passed vacuum_inside_transaction
pg10 10.21 (Debian 10.21-1.pgdg90+1) passed vacuum_inside_transaction

同类错误代码

Class 25 事务状态无效 下的其他成员。