You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何通过PgBouncer执行pgbench测试时,查询量提升TPS反而上升?

Postgres+PgBouncer下pgbench测试TPS随查询数上升的原因分析

问题背景

使用Postgres 13搭配PgBouncer执行pgbench测试时发现:提升客户端连接数与单客户端查询数量(-t参数)时,TPS(每秒事务数)反而上升,与“负载提升TPS下降”的预期相反;但直接连接数据库端口(不经过PgBouncer)时,负载提升会导致性能下降甚至数据库崩溃。


测试数据

通过PgBouncer(端口6544)的测试结果

固定客户端连接数700、工作进程数8,调整单客户端查询数(-t):

# -t 50(只读模式-S)
pgbench -U postgres -h .... -p 6544 datafactory -c 700 -j 8 -t 50 -S
latency average = 1591.633 ms
tps = 439.799988 (including connections establishing)
tps = 442.163375 (excluding connections establishing)

# -t 100
pgbench -U postgres -h ... -p 6544 datafactory -c 700 -j 8 -t 100 -S
latency average = 1286.131 ms
tps = 544.268178 (including connections establishing)
tps = 545.953341 (excluding connections establishing)

# -t 300
pgbench -U postgres -h ... -p 6544 datafactory -c 700 -j 8 -t 300 -S
latency average = 1246.031 ms
tps = 561.783731 (including connections establishing)
tps = 562.399700 (excluding connections establishing)

降低查询数量时TPS骤降:

pgbench -U postgres -h .. -p 6544 datafactory -c 700 -j 8 -t 10 -S
latency average = 8633.526 ms
tps = 81.079273 (including connections establishing)
tps = 81.465337 (excluding connections establishing)

直接连接Postgres(端口5433)的测试结果

固定客户端连接数250、工作进程数8,调整单客户端查询数:

# -t 500
pgbench -U postgres -h ... -p 5433 datafactory -c 250 -j 8 -t 500
latency average = 2155.394 ms
tps = 115.988055 (including connections establishing)
tps = 116.134037 (excluding connections establishing)

# -t 700
pgbench -U postgres -h ... -p 5433 datafactory -c 250 -j 8 -t 700
latency average = 835.555 ms
tps = 299.202467 (including connections establishing)
tps = 299.228977 (excluding connections establishing)

直接连接时出现数据库崩溃:

pgbench -U postgres -h ... -p 5433 datafactory -c 250 -j 8 -t 1000
WARNING:  terminating connection because of crash of another server process

pgbench -U postgres -h ... -p 5433 datafactory -c 250 -j 8 -t 700
connection to database "datafactory" failed:
FATAL:  the database system is in recovery mode

PgBouncer配置

listen_port = 6544
listen_addr = '*'
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
auth_proxy = on
auth_failure_threshold = 3
auth_inactivity_period = 60
auth_last_size = 10
log_audit = 1
logfile = /pgerrorlogs/tkldd-ldisu0001/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
admin_users = pgbouncer
max_client_conn = 1000
pool_mode = transaction
min_pool_size = 0
default_pool_size = 30
max_db_connections = 30
max_user_connections = 30
ignore_startup_parameters = extra_float_digits

原因分析

  1. PgBouncer连接池的核心作用
    配置中pool_mode = transaction(事务级连接池)且max_db_connections = 30,意味着不管客户端连接有多少(比如700),实际打到Postgres的连接数被严格控制在30个以内。Postgres基于进程模型,过多数据库连接会导致CPU上下文切换暴涨、内存耗尽,反而降低性能。PgBouncer通过连接池将大量客户端请求合并到少量数据库连接上,避免了连接风暴,让数据库能高效处理请求。

  2. 查询数量(-t)对开销的影响
    当-t值很小时(比如10),每个客户端仅执行10次查询,连接建立、认证的开销占比极高——即使PgBouncer复用连接,客户端频繁的连接断开、请求初始化也会消耗大量资源,导致TPS无法提升。而当-t增大时,每个客户端的查询次数变多,连接复用的效率被充分发挥,初始化开销被分摊到更多事务上,TPS自然上升;当-t从100到300时TPS增长放缓,说明已经接近数据库的处理瓶颈。

  3. 直接连接的性能崩溃逻辑
    直接连接时,250个客户端会建立250个Postgres数据库连接,远超过Postgres的最佳连接数(通常为CPU核心数*2+1)。过多连接会引发:

    • CPU上下文切换频繁,每个连接的CPU时间片被严重压缩
    • 内存占用剧增(每个Postgres连接需数MB内存),可能触发OOM导致进程崩溃
    • 数据库锁竞争加剧,事务等待时间变长
      这就是直接连接时性能下降甚至数据库崩溃的核心原因。

总结

PgBouncer的连接池机制规避了Postgres在高连接数下的性能劣化问题,而单客户端查询数量的提升充分利用了连接复用的优势,分摊了连接开销,因此TPS随查询数上升;直接连接时没有连接池的保护,过多数据库连接直接压垮Postgres,导致性能下降甚至崩溃。

内容的提问来源于stack exchange,提问作者Gerzzog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:16:23