Skip to main content
node-postgres (即 pg 包) 是 Node.js 生态中使用最广泛的 Postgres 驱动程序。在本指南中,您将通过启用完整 TLS 证书验证的 pg.Pool 连接到 ClickHouse Managed Postgres,创建两张表,在事务中完成账户间转账,并通过一个简单的 node:http 服务器对外提供数据。

前置条件

  • Node.js 20.6 或更高版本 (需使用其内置的 --env-file 标志) 。本指南已在 Node.js 24.21.0 和 pg 8.23.1 环境下测试通过。
  • 一个 ClickHouse Cloud 账户
  • psql,用于创建数据库

创建 ClickHouse Managed Postgres 服务

在 ClickHouse Cloud 控制台中,点击 New service,然后选择 Postgres。实例会在几分钟内就绪。完整操作流程请参阅快速入门。

获取连接详细信息

在服务的左侧边栏中点击 Connect。选中 Directly 后,从 url 选项卡中复制连接 URL。保持 Use SSL 关闭:应用会在代码中传入 CA 证书,而不是通过 URL 传入 (请参阅配置连接池) 。 本指南通过端口 5432 直接连接 Postgres。长期运行的 Node.js 服务器已通过 pg.Pool 维护自己的连接池,因此无需在 Postgres 前再加一层连接池器。如果您需要运行大量进程或 serverless 函数,请改用内置的 PgBouncer,详见使用 PgBouncer。 接下来,下载实例的 CA 证书。打开 Use SSL 并点击 Download CA certificate,或前往 Settings → CA Certificate → Download CA certificate。每个实例的证书都是唯一的。

设置项目

新建一个项目并安装 pg:
要集成到现有应用中?请跳过 mkdir 和 npm init -y。在您的项目中运行 npm install pg,然后直接进入创建数据库一节。
本指南中的示例均为扩展名为 .mjs 的 ES 模块,因此无论您的 package.json 使用的是 CommonJS 还是 ES 模块,示例都能正常运行。

创建数据库

将下载的 <service-name>-ca-certificate.pem 文件移动到项目目录中,并重命名为 ca-certificate.pem。然后为应用创建数据库:
创建一个 .env 文件,在其中填入您复制的连接 URL (将其中的数据库名称改为 guide_nodejs) 以及证书路径:
.env
如果密码中包含 @、/ 或 # 等字符,请在 URL 中对这些字符进行百分号编码。

配置连接池

创建 db.mjs,并在其中导出一个连接池,供应用的其他部分共享使用:
db.mjs
传入 ssl: { ca } 的效果等同于 sslmode=verify-full:pg 会检查服务器证书是否由您实例的 CA 签发,以及证书是否与主机名匹配。rejectUnauthorized 默认为 true,请勿将其设为 false。
不要将 ssl 与 URL 中的 SSL 参数混用如果 DATABASE_URL 包含 sslmode 或 sslrootcert,pg 会根据 URL 构建 TLS 设置,并忽略 ssl 对象。例如,以 ?sslmode=verify-full 结尾但不含 sslrootcert 的 URL 会覆盖您的 ca,导致连接失败并报错 unable to verify the first certificate。在代码中传入 ssl 时,请勿在 DATABASE_URL 中包含 SSL 参数。另请注意:
  • 如果既未传入 ssl 对象,URL 中也没有 sslmode,pg 将不使用 TLS,也不会验证服务器。
  • pg 会读取 PGHOST、PGUSER、PGPASSWORD 等变量,但不会读取 PGSSLROOTCERT。因此,仅靠 Connect 弹窗中 env 选项卡里的变量无法验证服务器。
  • 如果您希望将所有配置都放在 URL 中,也可以直接使用开启 Use SSL 后 Connect 弹窗所显示的 URL,它同样适用于 pg,例如 ...?sslmode=verify-full&sslrootcert=ca-certificate.pem。此时请移除 ssl 选项,并注意 sslrootcert 是相对于启动 Node.js 时所在的目录解析的。

创建 schema

创建 setup.mjs。该脚本会创建表,通过参数化查询插入两个账户,然后再将其读取出来:
setup.mjs
请始终以参数 ($1、$2、…) 的形式传递值,而不要将其拼接到 SQL 字符串中。pg 会将这些值与查询文本分开发送,从而防止 SQL 注入。JavaScript 数组会映射为 Postgres 数组,如 ANY($1) 查询所示。 运行:
pg 会以字符串形式返回 numeric (以及 bigint) 类型的值,以免丢失精度。如需数值,请显式转换。

在事务中运行查询

事务必须在同一个连接上执行,因此请使用 pool.connect 从连接池中获取一个客户端,并务必在用完后将其释放。创建 transfer.mjs:
transfer.mjs
不要使用 pool.query 执行事务中的语句:每次调用 pool.query 都可能在不同的连接上运行。

通过 HTTP 提供数据

创建 server.mjs。它在端口 3107 上以 JSON 格式提供账户和转账数据,可接收新的转账,并在收到 SIGINT (Ctrl+C) 或 SIGTERM 时正常关闭:
server.mjs
只需在进程关闭时调用一次 pool.end,而不是每处理完一个请求就调用。它会等待所有已借出的客户端归还,然后关闭全部连接。

验证

启动服务器:
在另一个终端中,先执行一次转账,然后再分别尝试一笔会导致账户透支的转账和一笔转入不存在账户的转账:
第三笔转账在失败前已从 alice 的账户中扣款,但 ROLLBACK 撤销了这笔扣款。在浏览器中打开 http://localhost:3107/accounts 即可查看余额。响应如下所示:
要确认该连接使用的是经过验证的 TLS,请查询 pg_stat_ssl:
如果将 DATABASE_CA_CERT 指向其他任何证书,连接都会失败并报错 unable to verify the first certificate,这说明服务器证书确实经过了校验。 最后,按 Ctrl+C 停止服务器。它会先输出 SIGINT received, shutting down,然后输出 Pool closed。 你也可以在控制台中查看数据。打开 SQL 控制台,展开 guide_nodejs 数据库,然后打开 accounts 表:

使用 PgBouncer

如需通过内置的 PgBouncer 连接,请在 Connect 弹窗中选择 via PgBouncer,并在 DATABASE_URL 中使用端口 6432。无需修改代码,且可继续使用同一 CA 证书。 PgBouncer 以事务池模式运行,因此每个事务都可能在不同的 Postgres 连接上执行。使用 pg 时:
  • 参数化查询、命名预处理语句 (pool.query({ name, text, values })) 以及使用 pool.connect 的事务均可按本指南所示方式正常使用。
  • SQL 级别的 PREPARE 和 EXECUTE,以及通过 SET 设置的会话设置,都不会跨事务保留。请改为在事务内部使用 SET LOCAL。
  • pg_stat_ssl 反映的是 PgBouncer 与 Postgres 之间的连接,因此上文的 TLS 检查查询会返回 ssl: false。应用与 PgBouncer 之间的连接仍会经过验证:若 CA 证书有误,连接同样会失败。

后续步骤

最后修改于 2026年10月14日