仅使用单个Postgres客户端实例时为何报FATAL #53300客户端过多错误
问题原因
- 你对
ConnectToDB()只创建唯一数据库实例的认知是正确的,问题核心是PostgreSQL连接数上限和go-pg连接池配置不匹配。 - PostgreSQL服务默认的
max_connections配置值为100,其中预留3个连接给超级用户,普通业务可用的连接仅97个。 pg.DB本质是数据库连接池,你没有显式配置PoolSize参数时,go-pg默认的最大连接数可能等于甚至超过PostgreSQL的连接上限。500个goroutine同时发起插入请求时,连接池会尝试创建更多连接满足并发需求,一旦总连接数超过PostgreSQL上限,就会抛出too many clients already错误。
解决方案
你可以任选一种或者组合使用以下方案解决问题:
- 显式设置go-pg连接池的最大连接数,数值要小于PostgreSQL的
max_connections,示例配置如下:
db = pg.Connect(&pg.Options{ User: "username", Database: "dbName", PoolSize: 80, // 自定义连接池最大连接数,超过该值的请求会排队等待空闲连接 })
- 调大PostgreSQL服务的连接上限:修改postgresql.conf配置文件中的
max_connections参数,调整到大于你的连接池最大连接数的数值,修改完成后重启PostgreSQL服务即可生效。 - 限制业务并发数:通过worker池控制同时执行插入操作的goroutine数量,避免短时间大量请求压满数据库连接,比如启动20个固定worker处理500个插入任务,从源头控制并发量级。
额外注意
你的代码存在变量遮蔽的不规范写法:main函数中db := ConnectToDB()的短变量声明创建了一个局部db变量,覆盖了全局定义的db变量,虽然当前逻辑下不影响功能,但后续如果修改代码很容易引发逻辑错误,建议修改局部变量名或者直接使用全局变量。
内容的提问来源于stack exchange,提问作者godwa_rao
相关产品推荐
相关产品推荐

