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

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

Wiki / SQLSTATE

25006 — 只读 SQL 事务(read_only_sql_transaction)

命令试图在只读事务中写入数据。

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

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

aliases
未知
class name
Invalid Transaction State
condition name
read_only_sql_transaction
lang
en
sqlstate
25006

版本定义 PG 18

25006 — 只读 SQL 事务(read_only_sql_transaction)

速览 {#at-a-glance}

25006 表示命令试图在只读事务中写入。选定案例在 SET TRANSACTION READ ONLY 后执行 CREATE TABLE,观察到 INERROR,回滚后离开只读事务再建表。

含义 {#meaning}

该码覆盖多个保护点。PreventCommandIfReadOnly 把命令名填入 cannot execute %s in a read-only transaction;固定源码还包含恢复期间临时表和复制原点的专用报文。选定案例覆盖普通显式只读事务路径,而备用机或恢复路径可能使用不同的命令相关报文。

诊断 {#diagnosis}

记录精确命令、SQLSTATE、严重级别和事务状态。重试前检查有效的 SHOW transaction_read_only,并在需要判断服务器边界时检查 pg_is_in_recovery();同时确认连接池是否把连接路由到了备用机。选定运行中 CREATE TABLE 返回 25006,使显式事务块进入 INERROR;复用会话前必须 ROLLBACK。离开只读事务后再次 CREATE TABLE 成功。

处理 {#response}

先判断操作是否应放在只读事务中。若必须写入,应在主库的可写事务中执行或移出只读块;失败块先回滚,再把连接归还连接池。备用机或恢复期间的 25006 需要把操作路由到主库;在同一只读目标上重试写入不会改变访问模式。

源码报文 {#messages}

核心 utility 路径的源码模板是 cannot execute %s in a read-only transaction;在恢复目标上,同一 utility 保护会使用 cannot execute %s during recovery,恢复期间临时表和复制原点也有各自的固定文本。%s 是实际命令名,不能脱离路径当作一条静态报文。

实测诊断 {#observed}

18.6 (Homebrew) / latest:SQLSTATE 25006;主报文 cannot execute CREATE TABLE in a read-only transaction;状态 INERROR → IDLE;修复后关系行数 0;最终状态 IDLE。 10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 25006;主报文 cannot execute CREATE TABLE in a read-only transaction;状态 INERROR → IDLE;修复后关系行数 0;最终状态 IDLE。

代表案例 {#case}

运行器从共享语句清单(registry)读取下列 setup、只读事务、回滚和事务块外修复语句;完整断言、环境和清理见 案例导出。

-- create
CREATE TABLE items(id integer PRIMARY KEY, note text NOT NULL);
-- begin
BEGIN;
-- read_only
SET TRANSACTION READ ONLY;
-- trigger
CREATE TABLE blocked(id integer PRIMARY KEY);
-- rollback
ROLLBACK;
-- repair
CREATE TABLE blocked(id integer PRIMARY KEY);
-- verify
SELECT count(*) FROM blocked;

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

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

版本与边界 {#versions}

选定的 CREATE TABLE 案例在 PostgreSQL 18.6 与 10.21 通过,主报文相同,并完成 INERROR → IDLE 恢复和修复后建表。其他 25006 源码路径不在本运行案例范围内。

相关 {#related}

25P02 失败 SQL 事务、25001 活动 SQL 事务、25P03 事务空闲超时。

来源 {#sources}

  • src.errcodes.18.6 (SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)
  • src.calls.REL_18_6 — raw/calls/REL_18_6.jsonl (SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)
  • src.utility.18.6 (SHA-256 7aae5d07628b6debf8456d1d4ea96f28912232192e56ea25773b4c4b61235a00)
  • src.namespace.18.6 (SHA-256 8c9e6a99e84fa2cec8a9b1de2ecbe3966a13f4ad68c6ccfbfb8134a754d73e56)
  • src.origin.18.6 (SHA-256 81e5d5b4539b67bb372f0f0a05395af900c322cdbcec8a4b1f358333a16e6518)
  • doc.set-transaction.18.6 (SHA-256 33554463a2c9da1cf2c72cc27d4647d557204bb13a03cfeccb1b83f237a46589) · official documentation

比较版本

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

cases · read_only_transaction
{
  "assertions": [
    "SQLSTATE is 25006",
    "The CREATE TABLE read-only diagnostic is exact",
    "The failed transaction is INERROR, ROLLBACK restores IDLE",
    "The table can be created after leaving read-only mode"
  ],
  "case_id": "read_only_transaction",
  "cleanup": "Drop the case schema with an owner connection.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "A runner-owned disposable target is provisioned."
  ],
  "repair": "Follow the explicit transaction or source boundary described by the case.",
  "trigger": "Run CREATE TABLE after SET TRANSACTION READ ONLY.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity
{
  "claim_id": "identity",
  "limits": "The same code covers more than one read-only/recovery guard.",
  "method": "Read the fixed condition row and macro.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "25006 is read_only_sql_transaction in Class 25."
}
claims · utility-path
{
  "claim_id": "utility-path",
  "limits": "The %s substitution is command-specific; recovery and parallel-operation paths have their own conditions/messages.",
  "method": "Trace PreventCommandIfReadOnly and the documented read-only command restrictions.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.utility.18.6",
    "src.calls.REL_18_6",
    "doc.set-transaction.18.6"
  ],
  "statement": "PreventCommandIfReadOnly formats the SQL command name into “cannot execute %s in a read-only transaction”; CREATE TABLE is one ordinary utility path."
}
claims · other-paths
{
  "claim_id": "other-paths",
  "limits": "Those recovery paths were not constructed by the selected ordinary read-only transaction case.",
  "method": "Read the additional fixed source report groups.",
  "position": 2,
  "runtime": [],
  "sources": [
    "src.namespace.18.6",
    "src.origin.18.6"
  ],
  "statement": "The fixed source also uses 25006 for temporary-table creation during recovery and replication-origin manipulation during recovery."
}
claims · runtime
{
  "claim_id": "runtime",
  "limits": "The case covers the ordinary explicit read-only utility path, not recovery-only temporary-table or replication-origin paths.",
  "method": "Read the selected summaries and structured diagnostics.",
  "position": 3,
  "runtime": [],
  "sources": [
    "runtime",
    "runtime.25006-batch2-latest-20260909.latest",
    "runtime.25006-batch2-pg10-20260909.pg10"
  ],
  "statement": "The selected read-only CREATE TABLE case returned 25006 on PostgreSQL 18.6 and 10.21, entered INERROR, recovered after ROLLBACK, and created the relation outside the read-only transaction."
}
claims · recovery-utility
{
  "claim_id": "recovery-utility",
  "limits": "The %s substitution is command-specific; the selected runtime did not run on a standby or recovery target.",
  "method": "Read the recovery guard and resolved report group in utility.c.",
  "position": 4,
  "runtime": [],
  "sources": [
    "src.utility.18.6",
    "src.calls.REL_18_6"
  ],
  "statement": "The same fixed utility source uses 25006 during recovery with the command-specific message \"cannot execute %s during recovery\"; this is separate from the selected ordinary read-only transaction path."
}
messages · utility
{
  "limits": "The %s substitution is the command name.",
  "message_id": "utility",
  "path": "",
  "position": 0,
  "raw": {
    "id": "utility",
    "limits": "The %s substitution is the command name.",
    "primary_template": "cannot execute %s in a read-only transaction",
    "severity_source": "ERROR",
    "sources": [
      "src.utility.18.6"
    ],
    "sqlstate": "25006"
  },
  "severity": "ERROR",
  "sources": [
    "src.utility.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot execute in a read-only transaction",
      "position": 0,
      "role": "",
      "template": "cannot execute %s in a read-only transaction"
    }
  ]
}
messages · utility-recovery
{
  "limits": "Recovery-only utility path; %s is the command name and this was not the selected ordinary read-only case.",
  "message_id": "utility-recovery",
  "path": "",
  "position": 1,
  "raw": {
    "id": "utility-recovery",
    "limits": "Recovery-only utility path; %s is the command name and this was not the selected ordinary read-only case.",
    "primary_template": "cannot execute %s during recovery",
    "severity_source": "ERROR",
    "sources": [
      "src.utility.18.6"
    ],
    "sqlstate": "25006"
  },
  "severity": "ERROR",
  "sources": [
    "src.utility.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot execute during recovery",
      "position": 0,
      "role": "",
      "template": "cannot execute %s during recovery"
    }
  ]
}
messages · recovery-temp
{
  "limits": "A recovery-only path; not the selected case.",
  "message_id": "recovery-temp",
  "path": "",
  "position": 2,
  "raw": {
    "id": "recovery-temp",
    "limits": "A recovery-only path; not the selected case.",
    "primary_template": "cannot create temporary tables during recovery",
    "severity_source": "ERROR",
    "sources": [
      "src.namespace.18.6"
    ],
    "sqlstate": "25006"
  },
  "severity": "ERROR",
  "sources": [
    "src.namespace.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot create temporary tables during recovery",
      "position": 0,
      "role": "",
      "template": "cannot create temporary tables during recovery"
    }
  ]
}
messages · recovery-origin
{
  "limits": "A recovery-only path; not the selected case.",
  "message_id": "recovery-origin",
  "path": "",
  "position": 3,
  "raw": {
    "id": "recovery-origin",
    "limits": "A recovery-only path; not the selected case.",
    "primary_template": "cannot manipulate replication origins during recovery",
    "severity_source": "ERROR",
    "sources": [
      "src.origin.18.6"
    ],
    "sqlstate": "25006"
  },
  "severity": "ERROR",
  "sources": [
    "src.origin.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot manipulate replication origins during recovery",
      "position": 0,
      "role": "",
      "template": "cannot manipulate replication origins during recovery"
    }
  ]
}
runtimes · runtime.25006-batch2-latest-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "read_only_transaction"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25006/cases.json",
      "sha256": "2009137faa2d1ebbbfa4dedfc1be073f9ea41b4bedd6c0acb34f3215ae37e25f"
    },
    "case_status": "passed",
    "cases": [
      "read_only_transaction"
    ],
    "id": "runtime.25006-batch2-latest-20260909.latest",
    "observed": {
      "after_error": "INERROR",
      "after_rollback": "IDLE",
      "final_status": "IDLE",
      "primary": "cannot execute CREATE TABLE in a read-only transaction",
      "repair_relation": "\"c25006_read_only_transaction\".\"blocked\"",
      "rows_after_repair": 0,
      "sqlstate": "25006"
    },
    "raw": "verify/results/25006-batch2-latest-20260909/latest/raw.jsonl",
    "raw_sha256": "b506359510adfe87c3fb8dbf50ed863b7fcdaad5b6bbb7ebf910ecec38c80780",
    "run_id": "25006-batch2-latest-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/25006/snippets.json",
      "sha256": "62db30e401b1f72fa50958d0ac612b2b1eb636299532dd1ad246c167e4f9fadf"
    },
    "status": "passed",
    "summary": "verify/results/25006-batch2-latest-20260909/latest/summary.json",
    "summary_sha256": "24fcf5d910c49c64eb3277bc4642190fe182f1ae2b731b2dffb0a5474c0189fe",
    "target": "latest",
    "target_status": "passed"
  },
  "run_id": "25006-batch2-latest-20260909",
  "runtime_id": "runtime.25006-batch2-latest-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.25006-batch2-pg10-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "read_only_transaction"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25006/cases.json",
      "sha256": "2009137faa2d1ebbbfa4dedfc1be073f9ea41b4bedd6c0acb34f3215ae37e25f"
    },
    "case_status": "passed",
    "cases": [
      "read_only_transaction"
    ],
    "id": "runtime.25006-batch2-pg10-20260909.pg10",
    "observed": {
      "after_error": "INERROR",
      "after_rollback": "IDLE",
      "final_status": "IDLE",
      "primary": "cannot execute CREATE TABLE in a read-only transaction",
      "repair_relation": "\"c25006_read_only_transaction\".\"blocked\"",
      "rows_after_repair": 0,
      "sqlstate": "25006"
    },
    "raw": "verify/results/25006-batch2-pg10-20260909/pg10/raw.jsonl",
    "raw_sha256": "8aa0068ea4575ffc24bc86d329a039a63c80f5e218cad36e9e6bfa3075c8c731",
    "run_id": "25006-batch2-pg10-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/25006/snippets.json",
      "sha256": "62db30e401b1f72fa50958d0ac612b2b1eb636299532dd1ad246c167e4f9fadf"
    },
    "status": "passed",
    "summary": "verify/results/25006-batch2-pg10-20260909/pg10/summary.json",
    "summary_sha256": "9de68a1e3ec84530fad088519fe71f009fde4dfefd02bd27e15096fb6c5b498a",
    "target": "pg10",
    "target_status": "passed"
  },
  "run_id": "25006-batch2-pg10-20260909",
  "runtime_id": "runtime.25006-batch2-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.utility.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/tcop/utility.c",
  "position": 2,
  "sha256": "7aae5d07628b6debf8456d1d4ea96f28912232192e56ea25773b4c4b61235a00",
  "source_id": "src.utility.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/utility.c#L397-L448"
}
sources · src.namespace.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/catalog/namespace.c",
  "position": 3,
  "sha256": "8c9e6a99e84fa2cec8a9b1de2ecbe3966a13f4ad68c6ccfbfb8134a754d73e56",
  "source_id": "src.namespace.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/namespace.c#L4418-L4437"
}
sources · src.origin.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/replication/logical/origin.c",
  "position": 4,
  "sha256": "81e5d5b4539b67bb372f0f0a05395af900c322cdbcec8a4b1f358333a16e6518",
  "source_id": "src.origin.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/replication/logical/origin.c#L189-L200"
}
sources · doc.set-transaction.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/sql-set-transaction.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/ref/set_transaction.sgml",
  "position": 5,
  "sha256": "33554463a2c9da1cf2c72cc27d4647d557204bb13a03cfeccb1b83f237a46589",
  "source_id": "doc.set-transaction.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ref/set_transaction.sgml#L131-L145"
}

来源引用

完整定义与证据 JSON

定义来源

center · PostgreSQL 18 · english-manuals:7845b825032955824315db9b8ee306470412f9a99ab3f92ae12eb8009ce1a2c5

正文语言: zh-Hans · english-manuals:7845b825032955824315db9b8ee306470412f9a99ab3f92ae12eb8009ce1a2c5