文档 / SQL 状态码 / Class 25 事务状态无效
25001 active_sql_transaction
活动 SQL 事务
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 必须早于任何查询。重复 BEGIN 的 WARNING 应保留已有事务,不要仅因警告就回滚。应按精确源码路径处理,不能机械套用 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 IDLE。
10.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 路径仅有源码证据。
来源
- 上游源码 doc/src/sgml/ref/vacuum.sgml
- 上游源码 src/backend/utils/errcodes.txt
- 上游源码 src/backend/replication/logical/logical.c 第 444–446 行
- 上游源码 src/backend/utils/time/snapmgr.c 第 1152–1154 行
- 上游源码 src/backend/utils/time/snapmgr.c 第 1409–1411 行
- 上游源码 src/backend/access/transam/xact.c 第 3654–3677 行
- 核验材料 raw/calls/REL_18_6.jsonl
证据
断言
每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。
-
25001 is active_sql_transaction in Class 25.
-
A utility such as VACUUM cannot run inside an explicit transaction block; xact.c formats the statement name into the 25001 primary message.
-
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.
-
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.
运行记录
| 目标 | 服务器版本 | 结果 | 覆盖案例 |
|---|---|---|---|
| latest | 18.6 (Homebrew) | passed | vacuum_inside_transaction |
| pg10 | 10.21 (Debian 10.21-1.pgdg90+1) | passed | vacuum_inside_transaction |
同类 SQL 状态码
| 状态码 | 条件名 | 宏名称 | 严重等级 | 版本 |
|---|---|---|---|---|
| 25000 | invalid_transaction_state | ERRCODE_INVALID_TRANSACTION_STATE |
ERROR | 7.4 |
| 事务状态无效的类别码,多见于内部状态检查。 | 活跃 | |||
| 25001 | active_sql_transaction | ERRCODE_ACTIVE_SQL_TRANSACTION |
ERROR | 7.4 |
| 命令不能在活动事务块中执行,如 VACUUM。 | 活跃 | |||
| 25002 | branch_transaction_already_active | ERRCODE_BRANCH_TRANSACTION_ALREADY_ACTIVE |
ERROR | 7.4 |
| 分支事务已经活动,范围窄于 25001。 | 活跃 | |||
| 25003 | inappropriate_access_mode_for_branch_transaction | ERRCODE_INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION |
ERROR | 7.4 |
| 分支事务使用了不适用的访问模式。 | 活跃 | |||
| 25004 | inappropriate_isolation_level_for_branch_transaction | ERRCODE_INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION |
ERROR | 7.4 |
| 分支事务使用了不适用的隔离级别。 | 活跃 | |||
| 25005 | no_active_sql_transaction_for_branch_transaction | ERRCODE_NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION |
ERROR | 7.4 |
| 分支事务缺少活动的 SQL 事务。 | 活跃 | |||
| 25006 | read_only_sql_transaction | ERRCODE_READ_ONLY_SQL_TRANSACTION |
ERROR | 7.4 |
| 命令试图在只读事务中写入数据。 | 活跃 | |||
| 25007 | schema_and_data_statement_mixing_not_supported | ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED |
ERROR | 7.4 |
| 事务中不支持混合模式语句与数据语句。 | 活跃 | |||
| 25008 | held_cursor_requires_same_isolation_level | ERRCODE_HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL |
ERROR | 7.4 |
| 持有游标要求与操作相同的事务隔离级别。 | 活跃 | |||
| 25P01 | no_active_sql_transaction | ERRCODE_NO_ACTIVE_SQL_TRANSACTION |
ERROR | 7.4 |
| 操作需要活动事务块,如自动提交下的 SAVEPOINT。 | 活跃 | |||
| 25P02 | in_failed_sql_transaction | ERRCODE_IN_FAILED_SQL_TRANSACTION |
ERROR | 7.4 |
| 事务已失败,后续语句被拒绝直到 ROLLBACK。 | 活跃 | |||
| 25P03 | idle_in_transaction_session_timeout | ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT |
ERROR | 9.6 |
| 会话在开放事务中空闲超时,被服务器终止。 | 活跃 | |||
| 25P04 | transaction_timeout | ERRCODE_TRANSACTION_TIMEOUT |
ERROR | 17 |
| 事务运行超过 transaction_timeout 被终止。 | 活跃 | |||