> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ClickHouse Managed Postgres FAQ

> 关于 ClickHouse Managed Postgres 的常见问题

export const BetaBadge = ({link, galaxyTrack, galaxyEvent}) => {
  if (link) {
    return <a href={link} target="_blank" rel="noopener noreferrer" className="betaBadge" onClick={galaxyTrack && galaxyEvent ? galaxyOnClick(galaxyEvent) : undefined}>
                <span>Beta</span>
            </a>;
  }
  return <a href="https://clickhouse.com/docs/reference/settings/beta-and-experimental-features#beta-features" className="betaBadge">
            <span>Beta 版功能</span>
        </a>;
};

<BetaBadge link="https://clickhouse.com/cloud/postgres" galaxyTrack={true} galaxyEvent="docs.managed-postgres.faq-beta" />

<h2 id="monitoring-and-metrics">
  监控与指标
</h2>

<h3 id="metrics-access">
  如何访问我的 ClickHouse Managed Postgres 实例指标？
</h3>

你可以直接在 ClickHouse Cloud 控制台中，进入 ClickHouse Managed Postgres 实例的 **Monitoring** 选项卡，监控 CPU、内存、IOPS 和存储使用情况。

此外，你还可以在 **Query Insights** 选项卡中查看 [Query Performance Insights](https://clickhouse.com/blog/postgres-query-insights-clickhouse-cloud)，对查询进行详细分析。

<h2 id="backup-and-recovery">
  备份与恢复
</h2>

<h3 id="backup-options">
  有哪些可用的备份选项？
</h3>

ClickHouse Managed Postgres 提供每日自动备份和持续 WAL 归档，支持将数据库恢复到 7 天保留期内的任意时间点。备份存储在对象存储中。

有关备份频率、保留期以及如何执行时间点恢复的完整信息，请参阅 [备份与恢复](/zh/products/managed-postgres/backup-and-restore) 文档。

<h2 id="infrastructure-and-automation">
  基础设施与自动化
</h2>

<h3 id="supported-cloud-providers">
  支持哪些云提供商？
</h3>

ClickHouse Managed Postgres 目前已在 AWS 上以 Public Beta 形式提供，GCP 则处于私有预览阶段。您可以在[此处](https://clickhouse.com/cloud/postgres#gcp-waitlist)加入 GCP 私有预览的候补名单，并阅读[公告](https://clickhouse.com/blog/postgres-managed-by-clickhouse-gcp-private-preview)了解更多信息。详情请参见[支持的云提供商](/zh/products/managed-postgres/overview#supported-cloud-providers)。

<h3 id="terraform-support">
  ClickHouse Managed Postgres 是否支持 Terraform？
</h3>

支持。您可以使用 ClickHouse Terraform provider 的 `clickhouse_postgres_service` 资源来创建和管理 ClickHouse Managed Postgres 服务。详见 [Terraform 参考](/zh/products/managed-postgres/terraform)。您也可以使用 ClickHouse Cloud 控制台或 [OpenAPI](/zh/products/managed-postgres/openapi) 创建和管理您的实例。

<h2 id="extensions-and-configuration">
  扩展和配置
</h2>

<h3 id="extensions-supported">
  支持哪些扩展？
</h3>

ClickHouse Managed Postgres 提供超过 90 个 PostgreSQL 扩展，包括 PostGIS、pgvector、pg\_cron 等热门扩展，以及更多其他扩展。有关可用扩展的完整列表和安装说明，请参阅 [扩展](/zh/products/managed-postgres/extensions) 文档。

<h3 id="config-customization">
  我可以自定义 PostgreSQL 配置参数吗？
</h3>

可以，您可以通过控制台中的 **Settings** 选项卡修改 PostgreSQL 和 PgBouncer 的配置参数。有关可用参数及其修改方法的详细信息，请参阅 [Settings](/zh/products/managed-postgres/settings) 文档。

<Tip>
  如果您需要当前尚未提供的参数，请联系 [support](https://clickhouse.com/support/program) 提出申请。
</Tip>

<h2 id="connection-pooling">
  连接池
</h2>

<h3 id="prepared-statement-errors">
  为什么通过 PgBouncer 连接时会出现 `prepared statement does not exist` 错误？
</h3>

ClickHouse Managed Postgres 以 **事务池化** (transaction pooling) 模式运行 PgBouncer。在此模式下，后端 Postgres 连接仅在单个事务期间分配给您的客户端，事务结束后即归还连接池——同一客户端的下一个事务可能会被分配到另一个后端连接上。

PgBouncer 会跟踪 **协议级预处理语句**，大多数驱动程序通过扩展查询协议 (`Parse`、`Bind` 和 `Execute` 消息) 发送这类语句。当某条语句在尚未准备过它的后端上执行时，PgBouncer 会先在该后端上完成预处理。每个后端连接最多保留 `max_prepared_statements` 条此类语句，默认值为 `200`。因此，大多数驱动程序使用默认设置即可通过 PgBouncer 正常工作。

以下情况无法通过 PgBouncer 正常工作：

* **SQL 级预处理语句。** PgBouncer 不会跟踪以 SQL 形式发送的 `PREPARE` 和 `EXECUTE`，因此 `EXECUTE` 可能会被发送到从未执行过相应 `PREPARE` 的后端上。
* **使用 SQL `DEALLOCATE` 释放语句。** PgBouncer 会在后端对语句进行重命名，因此按客户端语句名称执行的 `DEALLOCATE` 会失败。如果在事务内执行，该操作会导致事务中止，后续语句将报错 `current transaction is aborted`。基于 libpq 17 或更高版本构建的驱动程序改用协议级 `Close` 消息释放语句，PgBouncer 可以正确处理这种方式。
* **分多次往返发送的未命名语句。** 某些驱动程序模式会在一次往返中发送未命名语句的 `Parse`，在下一次往返中再发送其 `Bind`。PgBouncer 可能会将第二次往返分配到另一个后端上执行，从而报错 `unnamed prepared statement does not exist`，甚至在无任何报错的情况下执行另一个客户端的语句并返回其结果。

上述情况会产生类似以下的错误：

```text theme={null}
ERROR:  prepared statement "..." does not exist
ERROR:  unnamed prepared statement does not exist
ERROR:  prepared statement did not exist
```

以下症状通常都源于同一根本原因：

* 突发大量 `prepared statement does not exist` 错误，尤其是在回填数据或高并发写入期间
* 插入操作看似"静默失败"——语句报错后驱动程序进行重试，最终某个批次可能只被部分写入，甚至被丢弃
* 某条语句被释放后，事务失败并报 `current transaction is aborted` 错误
* 返回的行属于另一个查询

**解决方法：使用下表中与您的驱动程序对应的设置。** 如果您的驱动程序未在列表中，请将其升级到基于 libpq 17 或更高版本的发行版本，或在驱动程序中禁用服务器端预处理语句。

| 驱动程序 | 通过 PgBouncer |
| - | - |
| **node-postgres / pg** (Node.js) | 无需更改。 |
| **Bun.sql** (Bun) | 无需更改。如果出现 `prepared statement does not exist`，请设置 `prepare: false`。 |
| **Prisma** 搭配 `@prisma/adapter-pg` | 无需更改。在 Prisma 7 中，`pgbouncer=true` URL 参数不起作用。 |
| **psycopg 3** (Python, Django) | 使用 `psycopg[binary]` 或 libpq 17 及更高版本时无需更改。如果 libpq 版本较旧，请设置 `prepare_threshold=None`。Django 默认使用客户端绑定，因此无需更改。 |
| **asyncpg** (Python, SQLAlchemy) | 无需更改。如果在 SQLAlchemy 中通过 `statement_cache_size=0` 禁用了语句缓存，还需在 URL 中设置 `prepared_statement_cache_size=0`。 |
| **pgjdbc** (Java) | 无需更改。请使用 pgjdbc 42.7.5 或更高版本；更早的版本无法通过 PgBouncer 连接。参见 [`unsupported startup parameter`](#unsupported-startup-parameter)。 |
| **Npgsql** (.NET) | 无需更改：自动预处理默认关闭。通过 PgBouncer 连接时，请勿启用 `Max Auto Prepare` 或调用 `Prepare`；如确有必要，还需设置 `No Reset On Close=true`。 |
| **pgx** (Go) | 设置 `default_query_exec_mode=cache_describe` (或 `exec`) 。切勿使用 `describe_exec`，它会将未命名语句拆分到多次往返中执行。 |
| **Postgrex / Ecto** (Elixir) | 在 repo config 中设置 `prepare: :unnamed`。若使用命名语句，约 4 KB 大小的查询经由 PgBouncer 时可能会挂起。 |
| **sqlx** (Rust) | 无需进行预处理语句相关设置。请勿使用 `.persistent(false)` 或 `statement_cache_capacity(0)`。必须设置 `extra_float_digits(None)` 才能建立连接；参见 [`unsupported startup parameter`](#unsupported-startup-parameter)。 |
| **Active Record** (Ruby on Rails) | 使用 1.6 或更高版本的 `pg` gem 且 libpq 为 17 或更高版本时无需更改。否则，请在 `config/database.yml` 中设置 `prepared_statements: false`。 |
| **PDO** (PHP, Laravel) | 如果 `pdo_pgsql` 基于 libpq 17 或更高版本编译，则无需更改。否则，请设置 `PDO::ATTR_EMULATE_PREPARES => true`。 |

如果您的工作负载依赖 SQL 级别的 `PREPARE`，请**直接连接 PostgreSQL** (端口 5432) ，而不要经由 PgBouncer 连接池器。有关如何在池化端点与直连端点之间进行选择，请参见 [Connection](/zh/products/managed-postgres/connection)。

<h3 id="cached-plan-result-type">
  为什么迁移后查询会因 `cached plan must not change result type` 而失败？
</h3>

PgBouncer 会在其 Postgres 连接上保留预处理语句，并对相同的 SQL 文本复用这些语句。如果 schema 变更改变了某个查询所返回列的类型 (例如从 `integer` 改为 `bigint`) ，该查询通过 PgBouncer 执行时就会持续报错 `cached plan must not change result type`。即使从新的客户端连接发起，该查询依然会失败，直到 PgBouncer 替换其 Postgres 连接为止。某些驱动程序则会按过时的结果类型解码，在不报错的情况下返回错误的值。而如果通过直接连接，每个连接最多失败一次，随后便会恢复。

要恢复正常，请关闭 PgBouncer 针对该数据库的 Postgres 连接，PgBouncer 随后会建立新的连接。由于 PgBouncer 在本地连接 Postgres，其连接没有 `client_addr`。请通过直接连接 (端口 `5432`) ，以应用程序连接时所用的同一用户身份运行以下语句。该语句仅终止 PgBouncer 为您的应用程序用户建立的连接，因此当时正通过 PgBouncer 运行的事务会失败，而直接连接不受影响：

```sql theme={null}
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE datname = '<your_database>' AND usename = current_user
  AND client_addr IS NULL AND backend_type = 'client backend'
  AND pid <> pg_backend_pid();
```

使用未命名语句的驱动程序不受此影响，例如使用默认配置的 Npgsql、配置了 `prepare: :unnamed` 的 Postgrex，以及启用了 `cache_describe` 的 pgx。

<h3 id="unsupported-startup-parameter">
  为什么通过 PgBouncer 连接时会出现 `unsupported startup parameter` 错误？
</h3>

对于无法在其连接池中各个 Postgres 连接上一致生效的连接时设置，PgBouncer 会直接拒绝，并报错 `FATAL: unsupported startup parameter: ...` 或 `unsupported startup parameter in options: ...`。常见情况如下：

* **`extra_float_digits`**：pgjdbc 42.7.4 及更早版本 (例如搭配 Spring Boot 3 使用时) 以及 sqlx 会在每次建立连接时发送此参数。请将 pgjdbc 升级到 42.7.5 或更高版本；如使用 sqlx，请在 `PgConnectOptions` 上设置 `extra_float_digits(None)`。
* **连接字符串中的 `search_path` 及其他设置**：例如 JDBC URL 中的 `currentSchema`、Npgsql 连接字符串中的 `Search Path`、`options=-c ...`，或 Django 的 `OPTIONS["options"]`。请改用 `ALTER ROLE ... SET` 或 `ALTER DATABASE ... SET` 设置默认值，或在事务内使用 `SET LOCAL`，也可以绕过 PgBouncer 直接连接数据库。

`application_name` 和 `TimeZone` 均受支持。

<h3 id="session-state">
  为什么通过 PgBouncer 执行的 `SET` 命令无法持续生效？
</h3>

在事务池化模式下，会话级别的 `SET` 作用于执行它的 Postgres 连接，而不是你的客户端。你的客户端后续发起的事务可能会在没有该设置的其他连接上运行，而其他客户端则可能恰好使用带有该设置的连接。`SET ROLE` 也是如此，因此你切换到的角色可能会作用于其他客户端的查询。对于依赖会话状态的工作负载，请在事务内使用 `SET LOCAL`，或通过 `ALTER ROLE ... SET` 或 `ALTER DATABASE ... SET` 设置默认值，也可以直接连接数据库。

<h3 id="migration-advisory-locks">
  为什么通过 PgBouncer 执行迁移时会挂起或无法释放咨询锁？
</h3>

许多迁移工具会获取会话级咨询锁，确保同一时间只有一个迁移在运行，随后再用一条单独的语句释放该锁。经由 PgBouncer 时，释放语句可能在另一个 Postgres 连接上执行，导致锁残留在连接池中的某个连接上。此后的迁移便会一直等待，或因 `failed to release advisory lock` 等错误而失败，即使改用直接连接也是如此。使用会话咨询锁的工具包括 golang-migrate、sqlx、Kysely 的 `Migrator`、Rails、配置了 `transactional-lock=false` 的 Flyway，以及配置了 `migration_lock: :pg_advisory_lock` 的 Ecto。

请通过直接连接 (端口 `5432`) 运行迁移。泄漏的锁由空闲会话持有，而仍在运行的迁移则由活跃会话持有其锁。要清除泄漏的锁，请同样通过直接连接，仅终止数据库中持有咨询锁的空闲会话：

```sql theme={null}
SELECT pg_terminate_backend(l.pid) FROM pg_locks l
JOIN pg_stat_activity a ON a.pid = l.pid
WHERE l.locktype = 'advisory' AND a.state = 'idle'
  AND l.database = (SELECT oid FROM pg_database WHERE datname = current_database());
```

<h3 id="pgbouncer-vs-pg-connections">
  PgBouncer 中的 `max_client_conn` 设置是什么意思？它与 Postgres 中的 `max_connections` 有什么关系？
</h3>

它们控制的是不同的对象：

* **Postgres `max_connections`** 限制的是 PostgreSQL 自身的 **后端** 连接数。这才是成本较高的那个限制——每个 后端 都会占用内存和一个进程槽位。
* **PgBouncer `max_client_conn`** 限制的是连接池器中可同时打开的 **客户端** 连接数。PgBouncer 会将大量客户端连接复用到一组小得多的 后端 连接上。

PgBouncer 可接受的客户端连接数是 Postgres 后端数量的数倍。例如，`max_connections` 设置为 `500` 的实例，在连接池器处可接受 `2500` 个客户端连接。如果你在连接池器这一层看到连接错误，那么相比达到醒目的客户端连接上限，更有可能是触及了每个连接池的 后端 限制 (`default_pool_size`，或每个数据库的 `max_db_connections`) 。

要查看你的实例的配置值，请通过 PgBouncer (端口 `6432`) 连接到特殊的 `pgbouncer` 数据库，并运行 `SHOW CONFIG`：

```bash theme={null}
psql "postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:6432/pgbouncer?sslmode=verify-full&sslrootcert=ca-certificate.pem" -c "SHOW CONFIG;"
```

<h2 id="database-capabilities">
  数据库功能
</h2>

<h3 id="multiple-databases-schemas">
  我可以创建多个数据库和 schema 吗？
</h3>

可以。ClickHouse Managed Postgres 提供完整的 PostgreSQL 原生功能，包括在单个实例中支持多个数据库和 schema。您可以使用标准的 PostgreSQL 命令来创建和管理数据库及 schema。

<h3 id="rbac-support">
  是否支持基于角色的访问控制 (RBAC) ？
</h3>

您对自己的 ClickHouse Managed Postgres 实例拥有完整的 superuser 访问权限，因此可以使用标准的 PostgreSQL 命令创建角色并管理权限。

<Note>
  计划于今年推出与控制台集成的增强 RBAC 功能。
</Note>

<h2 id="upgrades">
  升级
</h2>

<h3 id="version-upgrades">
  PostgreSQL 版本升级是如何处理的？
</h3>

无论是次要版本升级还是主版本升级，都是通过故障转移完成的，通常只会造成几秒钟的停机。您可以配置[计划升级](/zh/products/managed-postgres/upgrades#scheduled-upgrades)，以控制在哪些日期及哪个两小时 UTC 时段内应用升级。完整详情请参阅[升级](/zh/products/managed-postgres/upgrades)文档。

<h2 id="migration">
  迁移
</h2>

<h3 id="migration-tools">
  可用于迁移到 ClickHouse Managed Postgres 的工具有哪些？
</h3>

ClickHouse Managed Postgres 支持多种迁移方式：

* **pg\_dump 和 pg\_restore**：适用于较小的数据库或一次性迁移。请参阅 [pg\_dump 和 pg\_restore](/zh/products/managed-postgres/migrations/pg_dump-pg_restore) 指南。
* **逻辑复制**：适用于需要尽量减少停机时间的大型数据库。请参阅 [逻辑复制](/zh/products/managed-postgres/migrations/logical-replication) 指南。
* **PeerDB**：适用于从其他 Postgres 源进行基于 CDC 的复制。请参阅 [PeerDB 迁移](/zh/products/managed-postgres/migrations/peerdb) 指南。

<Note>
  全托管迁移体验即将推出。
</Note>
