PostgreSQL在线调整最大连接数方案设想

本文探讨了PostgreSQL在连接数满时如何在线调整最大连接数的问题,提出一个名为db_connlimit的新参数,旨在在不影响原生逻辑的情况下,通过reload方式动态调整连接数。文章介绍了参数的设计思路,对原生影响的考量,代码修改,以及不同场景下的测试验证,显示该方案在某些情况下能有效缓解连接数压力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景介绍

PostgreSQL的最大连接数在某些时候会成为一个让业务很苦恼的问题。业务连接数暴增,连接数打满,但又不能重启服务这种场景下,显得非常尴尬。最大连接数就只能重启调整,要想不停库,貌似“无解”。

为什么调整最大连接数需要重启,不能修改为reload方式?
这个问题不详细展开,简单来说最大连接数参数和共享内存及信号量等相关的,设置最大连接数后,在启动时系统会相应分配这些资源。那原生的最大连接数参数看起来只能是重启方式修改生效了。

原生pg除了max_connections,还可以ALTER USER / DATABASE … CONNECTION LIMIT connlimit通过user和 database这两个维度去动态调整连接数。不过只适用于比较特定的场景下,稍微推敲一番,就会发现大部分场景下不适用。比如同实例多database,多user,并且每个user需要一定数量的连接数,那瓶颈又回到了max_connections

思考了一番,决定尝试新增一个在线参数db_connlimit,可以动态调整最大连接数,参数级别为PGC_SIGHUP即reload生效。
默认值为-1,保持默认值,最大连接数还是沿用原生的逻辑。取值范围从-1(default)至max_connnections 。也就是说系统资源还是由max_connections参数来管理,db_connlimit参数只用来管理连接数个数,资源满足情况下适当放大max_connections,例如将db_connlimit设置为max_connections的一半,在连接数已满的情况下,可以继续增大db_connlimit,来缓解一些压力。

当然这个方案是存在问题的:例如未考虑版本差异。要想做到兼容所有版本,那么可以考虑HooK extensions 或者中间件方式,不过这样架构可能会更加复杂了。研发大佬肯定有成熟的方案,作为运维同学,我们就最后挣扎一下,验证下这个方案。

这里使用pg13.0进行测试。

二、问题思考

db_connlimit参数必须满足以下几点要求:

  1. 对原生影响要小,可以关闭(default为关闭)关闭后不影响原生逻辑;
  2. 可靠性,连接数达到最大时要和原生处理逻辑一致;
  3. 最大值生效问题,最大值必须小于等于max_connnections 当试图配置大于这个值时reload不能生效,并且保持原有值

三、代码修改

针对以上3个问题,依次来看:

  • 增加参数db_connlimit

global.c 设置全局变量DbConnlimit

/*
 * Modify by Nickxyang at 2021-06-07 PM
 * Add the global variable DbConnlimit.  
 */
int                     DbConnlimit = 100;
/*
 * Modify End at 2021-06-07 PM
 */

miscadmin.h

/*
 * Modify by Nickxyang at 2021-06-07 PM
 */
extern PGDLLIMPORT int DbConnlimit;
/*
 * Modify End at 2021-06-07 PM
 */

guc.c新增参数db_connlimit, 首个-1为default,第二个-1为最小值

/*
 * Modify by Nickxyang at 2021-06-07 PM
 * Add the parameter db_connlimit, you can modify the maximum number of connections online. 
 * The valid range is -1 (default) to Maxconntions. A value of -1 means that the parameter is not open.
 */
{
   
        {
   'db_connlimit', PGC_SIGHUP, CONN_AUTH_SETTINGS,
                gettext_noop('Sets the maximum number of concurrent connections, which can be set online.'),
                NULL
        },
        &DbConnlimit,
        -1, -1, MAX_BACKENDS,
        check_dbconnlimit, NULL, NULL
},
/*
 * Modify End at 2021-06-07 PM
 */

guc.c增加check函数,该函数由函数指针指向,在initdb以及start环节check该参数合法性

/*
 * Modify by Nickxyang at 2021-06-07 PM 
 */
static bool
check_dbconnlimit(int *newval, void **extra, GucSource source)
{
   
        if ((*newval + autovacuum_max_workers + 1 +
                max_worker_processes + max_wal_senders > MAX_BACKENDS) && *newval > MaxConnections)
                return false;
        return true;
}
/*
 * Modify End at 2021-06-07 PM
 */

postgresql.conf.sample

#db_connlimit = -1                      # range -1 to max_connections
  • 保证对原生影响不大,参数关闭时,不影响原生逻辑
  • 可靠性,保证达到最大连接数时,处理逻辑和原生一致

postinit.c 中InitPostgres函数

	/*
	 * Modify by Nickxyang at 2021-06-07 PM
	 *
	 * If the DbConnlimit parameter is configured 
	 * and the number of connections reaches DbConnlimit - ReservedBackends, 
	 * non-superuser will not be able to create new connections 
	 */
	if (DbConnlimit > 0 && DbConnlimit < MaxConnections)
	{
   
	        if (!am_superuser && !am_walsender
	                && ReservedBackends > 0 &&
	                !HaveNFreeProcs(MaxConnections - DbConnlimit + ReservedBackends))
	                ereport(FATAL,
	                                (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
	                                errmsg('remaining connection slots are reserved for n
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值