bigywater.tech
PostgreSQL · 17

PostgreSQL 为什么需要连接池:新建连接 1.82 ms 对复用 0.051 ms,max_connections 与吞吐、idle in transaction 实测

“PostgreSQL 为什么需要连接池、max_connections 该设多少、idle in transaction 是什么” 都可以直接量出来。这篇在本机(10 核)自己起一个 PostgreSQL 16.15,用 pgbench 量连接建立的代价、并发连接数对吞吐和延迟的影响、max_connections 的内存成本,并复现 idle in transaction 的超时断开。

82406 对 1393 tps
pgbench 只读,持久连接与每个事务重新建连接的吞吐
64 个连接
10 核机器上 pgbench -S 吞吐到顶(107795 tps),256 个连接时降到 99854 tps、延迟 2.564 ms
279MB → 513MB
max_connections 从 100 到 5000 时 shared_memory_size 的变化

建连成本

实测 · 本机执行输出
  每次新建连接:中位数 1.82 ms,p95 2.22 ms,最大 5.32 ms;1000 次共 1.88 s
  复用同一个连接:1000 次共 0.051 s,平均 0.051 ms/次

每个新连接 fork 一个后端进程,本机回环 trust 认证下中位数 1.82 ms;复用连接 0.051 ms。

短连接的代价

实测 · 本机执行输出
  持久连接:82406 tps,平均延迟 0.097 ms
  -C 每个事务重新建连接:1393 tps,平均延迟 5.743 ms

每个事务都新建连接,吞吐掉到持久连接的六十分之一。

并发数

实测 · 本机执行输出
      客户端数       tps       平均延迟 ms
         1     26220         0.038
         4     60556         0.066
         8     85762         0.093
        16     92692         0.173
        64    107795         0.594
       256     99854         2.564

吞吐在连接数是核数的几倍时到顶,再增加只会让延迟变长。

内存

实测 · 本机执行输出
  100 个空闲连接(每个都查过一次小表)的后端进程:共 101 个,RSS 中位数 9.9 MB,最小 4.2 MB,最大 10.0 MB(RSS 含共享内存里碰过的页,不是每个进程的私有内存)
  max_connections =   100:shared_memory_size = 279MB
  max_connections =   400:shared_memory_size = 293MB
  max_connections =  5000:shared_memory_size = 513MB

RSS 含共享页,不能乘连接数;max_connections 越大共享内存越大。

空闲事务

实测 · 本机执行输出
  pg_stat_activity 里按 state 统计: [('idle in transaction', 1)]
  设了 idle_in_transaction_session_timeout = 1s 之后,空闲 2 秒的事务连接再用: IdleInTransactionSessionTimeout: terminating connection due to idle-in-transaction timeout

idle in transaction 连接占名额、挡 VACUUM;idle_in_transaction_session_timeout 让服务端主动断开。

分步演示

连接成本实测
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / PostgreSQL 16.15(Homebrew);每个实验自己 initdb 一个数据目录,端口 9261 起,只监听 127.0.0.1,不碰本机已有的 5432 上的实例;命令行工具统一用 LC_ALL=C 取英文原文,路径换成 ;计时用 time.perf_counter 或 EXPLAIN ANALYZE 的 Execution Time,数字每次运行会有小幅抖动;实验结束后整个数据目录删除。本机 CPU 核数 10,pgbench scale = 10,max_connections = 400(第四篇另测);认证 trust、本机回环,没有 SCRAM 握手、TLS 和网络延迟,真实环境的连接建立更慢;每组 pgbench 跑 6 秒
    • 没有验证:pgbouncer / pgpool 等真实连接池(本机没有装);SCRAM 和 TLS 下的建连耗时;跨机器网络往返;Linux 上进程内存统计(PSS)的实际占用;远多于核数的连接数下更长时间的运行;PostgreSQL 其他大版本
    京ICP备2026067502号-1京公网安备11010502063487号