# 57014 — query_canceled：查询已取消

> 当正在执行的语句被取消（包括 statement_timeout）时，PostgreSQL 会报告 SQLSTATE 57014。应区分取消来源，检查事务状态，并确认后续操作安全。
---

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

`57014` 是 PostgreSQL 类别 57 `operator_intervention` 中的 `query_canceled` 条件。它表示服务器中断了某条语句。多个取消来源共用这个 SQLSTATE，因此必须结合主报文和服务器上下文，区分 statement timeout、客户端取消、恢复冲突或其他管理路径。

代表性案例在专用自动提交连接上设置 `statement_timeout` 为 100 ms，再执行 `pg_sleep(1)`。PostgreSQL 返回 `canceling statement due to statement timeout`；连接保持 `IDLE`，后续 `SELECT 1` 返回 `1`。这只证明本案例的超时路径及连接可用性，不能推断所有取消命令都没有副作用或拥有相同事务状态。

运行 `57014-registry-final-20260909` 在 PostgreSQL 18.6 和隔离的 PostgreSQL 10.21 上均通过。逐目标断言和结构化观察见[公开证据 JSON](../../data/evidence/57014.json)。

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

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `57014` |
| 条件名 | `query_canceled` |
| 状态 | `有效` |
| 已知存在于 | `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_QUERY_CANCELED` |
| 别名 | `—` |

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

## 含义与触发路径 {#meaning}

`statement_timeout` 为每条语句启动计时器，预算到期后请求 backend 处理中断。在固定源码路径中，`ProcessInterrupts` 使用 `ERRCODE_QUERY_CANCELED` 和 `canceling statement due to statement timeout` 报告错误。客户端取消使用相同 SQLSTATE 但主报文是 `canceling statement due to user request`；锁超时和某些恢复路径使用自己的报文或 detail。

取消会在可处理中断的点停止当前语句。它不等于所有关联请求的工作都已经停止，也不保证外部副作用已经撤销，更不保证无需回滚就能继续使用事务。必须结合事务边界、语句类型和取消来源确定清理方式。

## 报文与诊断 {#messages}

代表性操作是在专用自动提交连接上设置 100 ms 超时：

<!-- BEGIN SQLSTATE SNIPPET: statement_timeout_cancel -->
```sql
SET statement_timeout = '100ms';
SELECT pg_sleep(1);
SELECT 1;
```
<!-- END SQLSTATE SNIPPET -->

PostgreSQL 18.6 返回：

```text
SQLSTATE: 57014
severity: ERROR
message_primary: canceling statement due to statement timeout
source: postgres.c / ProcessInterrupts / line 3446
```

PG10 返回相同的主报文，对应源码行号为 3018。`57014` 没有统一的 detail 模板；如果客户端提供，应保存 message_detail、message_hint、上下文及被中断的语句。

## 诊断 {#diagnosis}

记录 SQLSTATE、严重级别、主报文、detail、hint、上下文、backend PID、语句文本、超时设置和取消来源。区分 statement timeout、lock timeout、客户端取消、管理员请求以及备用机恢复冲突。客户端诊断不完整时，可使用 SQLSTATE 和 backend PID 检查服务器日志。

检查错误后的事务状态。本案例的自动提交超时后为 `IDLE`，并成功执行 `SELECT 1`；显式事务中的错误可能让事务进入 `INERROR`，需要回滚。如果语句在出错前已改变行，应检查数据库实际状态，不要假定数据库之外的整个请求都能自动回滚。

## 处理与修复 {#response}

根据原因调整操作和预算：

- 优化或拆分过长查询，设置符合服务预算的超时。
- 将客户端或管理员取消视为控制决策，再判断应用是否应重试。
- 如果报文指向 lock timeout，应独立解决锁竞争；提高 statement timeout 不会修复锁队列。
- 显式事务中止后先回滚，再发送无关命令；对生命周期不受 PostgreSQL 控制的外部工作进行验证。

代表性后续查询返回 `1`，连接状态为 `IDLE`。这是自动提交 sleep 案例的修复断言，不保证被取消的写入、游标或事务都能原地继续。

## 版本与边界 {#versions}

目录在 PostgreSQL 7.4 的锁定定义中已观察到 `57014`，并持续到 8.4.22 的 pre-9.0 定义；随后在列出的所有正式快照直到 PostgreSQL 18.6 以及 PostgreSQL 19 Beta 3 预览中存在。这是 definition_only 的存在边界，不是确切实现引入版本或运行时使用断言。扫描范围内没有记录该条件的定义变化。

statement timeout 案例在 PostgreSQL 18.6 和 10.21 上均通过。该 SQLSTATE 还用于其他取消机制，而它们的报文和事务影响不同；本证据范围限定为自动提交连接上的服务器 statement timeout。

## 相关 {#related}

[`40P01` — `deadlock_detected`](../40p01/) 是锁管理器发现环后解决的死锁，不是超时预算。[`53300` — `too_many_connections`](../53300/) 是启动阶段容量失败。[`42P01` — `undefined_table`](../42p01/) 是解析阶段的名称错误。[`25P02` — `in_failed_sql_transaction`](../25p02/) 可能在取消使周围显式事务中止后出现。

## 来源 {#sources}

结构化证据记录在[公开证据 JSON](../../data/evidence/57014.json)中。源码记录固定到 PostgreSQL commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`；运行记录保留两个目标 ID 和结构化观察。

- `src.errcodes.18.6` — [`errcodes.txt`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt#L432-L438)
- `src.postgres.18.6` — [`postgres.c`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L3439-L3447)
- `doc.config.18` — [语句行为和 statement_timeout](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-STATEMENT-TIMEOUT)
- Runtime：latest 与 pg10 均为 `57014-registry-final-20260909`，结构化观察见[公开证据 JSON](../../data/evidence/57014.json)
