# 2D000 — invalid_transaction_termination（无效事务终止）

> PostgreSQL SQLSTATE 2D000 的来源与机制边界参考。
---

# 2D000 — invalid_transaction_termination（无效事务终止）

## 速览 {#at-a-glance}

`2D000` 是 SPI 在过程或子事务上下文尝试无效事务终止时使用的保护码。18.6 固定路径把它与正常显式 `COMMIT` 区分开来；本批不把所有过程级事务错误都归为 2D000，也不使用 RAISE 伪造 SQL 案例。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `2D000` |
| 条件名 | `invalid_transaction_termination` |
| 状态 | `有效` |
| 已知存在于 | `7.4` |
| 锁定快照 | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_INVALID_TRANSACTION_TERMINATION` |
| 别名 | `—` |

<!-- source facts: data/errcodes/2D000.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

`2D000` 是 SPI 的事务终止无效条件。固定 `spi.c` 路径在原子 SPI 上下文中拒绝 `SPI_commit`/`SPI_rollback`，并在子事务活动时分别拒绝提交或回滚。源码注释明确把限制与过程语言用子事务实现异常块联系起来。

## 诊断 {#diagnosis}

定位尝试控制事务的过程/函数和 SPI 调用者。区分允许控制事务的顶层 `CALL` 与原子 SPI 上下文中的函数或异常块，并检查是否仍处于嵌套子事务。固定源码报文包括 `invalid transaction termination`、`cannot commit while a subtransaction is active`、`cannot roll back while a subtransaction is active`；普通客户端 `COMMIT` 错误不能单独归类为这条路径。

## 处理 {#response}

把事务控制移到允许的过程边界，或先让外层过程/异常块结束活动子事务，再终止顶层事务。不要在同一禁止的 SPI 上下文里再次发送 `COMMIT`/`ROLLBACK`，也不要套用通用重试。本批只记录源码路径，不用 `RAISE` 或不忠实的 SQL 伪造运行案例。

## 版本 {#versions}

上面的锁定事实表记录项目快照范围内的目录存在情况。固定源码证据只覆盖下面声明的路径；不能仅从定义推导精确行为引入版本或更广的运行覆盖。

## 相关 {#related}

在改变过程或事务边界前，可先对照[25P01 无活动 SQL 事务](../25p01/)和[24000 游标状态无效](../24000/)。

## 来源 {#sources}

- [`src.errcodes.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt)（SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`）
- [`源码路径`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/executor/spi.c#L239-L241)（SHA-256 `7244b45f632583c72530832df901b788fe403c8857425dd13edb49d9f84b0c78`）
