# 08003 — 连接不存在（connection_does_not_exist）

> PostgreSQL SQLSTATE 08003（连接不存在，connection_does_not_exist）的源码证据、诊断与处理参考。
---

# 08003 — 连接不存在

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

SQLSTATE `08003` 是 Class `08` 中的 **connection_does_not_exist**。`08003` 表示当前 dblink 后端会话中不存在指定名称的连接句柄。它是句柄生命周期错误，不能证明远端服务器无法建立连接（08001）或已有 socket 失败（08006）。选定路径先断开 `missing_remote`，再证明可以打开、查询并断开真实句柄。

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

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

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

## 含义 {#meaning}

此条件来自 dblink 句柄查找，发生在执行任何远端 SQL 之前：当前后端没有与请求相符的命名连接。主报文按 `connection "%s" not available` 组装，因此名称指向本地句柄生命周期，而不是远端可达性。句柄缺失与 08001 建连失败、以及已有连接丢失的 08006 是不同问题。

句柄查找只发生在一个 PostgreSQL 后端中。连接池可能让两个客户端使用相同的应用层连接名，但它们的 dblink 句柄表并不共享；在一个后端创建 `working_remote`，不能修复另一个后端的 `missing_remote`。固定路径没有 DETAIL 或 HINT，因此首先要保留被引用的句柄名和发起调用的会话。

## 诊断 {#diagnosis}

检查准确的 dblink 名称以及拥有它的会话或连接池连接。主报文动态组装为 `connection "missing_remote" not available`；选定自动提交运行中的查找错误后仍为 `IDLE`，修复句柄返回远端 `1`，`dblink_disconnect` 返回 `OK`。

要把句柄查找失败和 socket 丢失分开。如果当前后端从未打开该名称，检查句柄创建路径和连接池分配；如果它曾打开而后续远端调用失败，则先收集该调用的诊断，再决定是否断开重建。在显式本地事务中，这个 dblink `ERROR` 遵循通常的事务中止边界，必须回滚或回到有意建立的保存点后才能执行无关语句。选定的 `IDLE` 是自动提交情形的结果。

## 处理 {#response}

在实际使用句柄的同一会话中创建它，或明确将不存在的句柄断开定义为幂等操作。真实远端操作结束后先核对结果，再关闭或重建句柄；不要因为一个会话忘记 dblink 名称就重连整个连接池。

自动提交时，在同一个后端完成打开、探测和断开就是完整生命周期。显式事务中应先恢复本地事务，再在同一后端重建句柄；新句柄成功并不能证明之前的远端操作已经提交。应在连接池诊断中记录句柄名和所有权，避免重连后把工作悄悄移到另一个会话。

## 实测诊断 {#messages}

固定的句柄查找路径以 `ERROR` 发出主报文 `connection "%s" not available`；请求的句柄名称是动态值，没有固定 DETAIL 或 HINT。只有客户端异常而没有这条服务器诊断，不能据此认定 08003。

因此，选定的主报文 `connection "missing_remote" not available` 是具体的名称查找结果，不是远端可达性测试。固定的 `ERROR` 在显式事务中可能使事务进入 `INERROR`；选定所有者为自动提交，所以错误后仍是 `IDLE`。

## 代表案例 {#case}

<!-- BEGIN SQLSTATE SNIPPET: dblink_missing_connection -->

此 SQL 块要求 `dblink` 断开从未打开的句柄，然后探测同一会话。

`runner_host`、`runner_port`、`runner_db` 和 `runner_user` 是运行器占位参数。手工执行时应替换为所有者具有 dblink 和远端连接权限的目标与登录角色。句柄属于当前会话：缺失查找、打开/探测和断开必须在同一后端中执行；选定案例使用自动提交。

```sql
CREATE EXTENSION IF NOT EXISTS dblink;
SELECT dblink_disconnect('missing_remote');
SELECT dblink_connect('working_remote', 'host=runner_host port=runner_port dbname=runner_db user=runner_user connect_timeout=5');
SELECT * FROM dblink('working_remote', 'SELECT 1') AS result(value integer);
SELECT dblink_disconnect('working_remote');
SELECT 1;
```

<!-- END SQLSTATE SNIPPET -->

18.6 运行记录 SQLSTATE 为 `08003`，主报文 `connection "missing_remote" not available`；错误后所有者会话为 `IDLE`。修复打开句柄返回 `OK`，远端返回 `1`，断开返回 `OK`；最终探针返回 `1`，状态 `IDLE`。10.21 也通过同样断言。

可下载的案例与证据投影分别是 [`08003 案例 JSON`](../../data/cases/08003.json) 和 [`作者证据`](../../data/evidence/08003.json)。运行器清单为 `verify/cases/08003/cases.json`；发布前会将页面 SQL 与共享注册表比对。

## 版本 {#versions}

上面的生成事实表记录锁定的目录快照和最早观察到的定义。本页自然运行范围是 PostgreSQL 18.6 与 10.21，不能据此推断所有中间版本的行为。

## 相关 {#related}

- [`08001` — sqlclient_unable_to_establish_sqlconnection](../08001/)
- [`08006` — connection_failure](../08006/)

## 来源 {#sources}

- `src.dblink-not-available.18.6` — `contrib/dblink/dblink.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `e4cfaec3a0a1e5d23fded584725e0f6cf7a17321ad99e5fe046e8b7f97416f15` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/contrib/dblink/dblink.c#L193-L195)).
- `src.dblink-not-available.10.23` — `contrib/dblink/dblink.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `2d542cc722ba361bd59990aaed7fe7c0f8e147155df5e5fcd56ee03b4dd27c61` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/contrib/dblink/dblink.c#L171-L173)).
- `src.calls.REL_18_6` / `src.calls.REL_10_23` — fixed local call scans, SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf` / `00d16d3eb01b71ccf1b245c8f3102f9d0ec9f36fb02777b8dd1b99fcb263040c`; these scans preserve the resolved call context used by the claims.
