“PostgreSQL 为什么需要连接池、max_connections 该设多少、idle in transaction 是什么” 都可以直接量出来。这篇在本机(10 核)自己起一个 PostgreSQL 16.15,用 pgbench 量连接建立的代价、并发连接数对吞吐和延迟的影响、max_connections 的内存成本,并复现 idle in transaction 的超时断开。
每次新建连接:中位数 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 timeoutidle in transaction 连接占名额、挡 VACUUM;idle_in_transaction_session_timeout 让服务端主动断开。