PostgreSQL的max_connections未生效,主因是shared_buffers不足或系统ulimit限制;MySQL连接数告警多因wait_timeout过长导致Sleep连接堆积;Python多进程下各worker独立占用连接需统一管控;盲目调高连接数会加剧内存与锁竞争。
PostgreSQL 的 max_connections 改了但没生效?检查 shared_buffers 和 OS 限制
改完 max_connections 却连不上新连接,大概率不是配置写错了,而是被底层卡住了。postgresql 启动时会校验几个硬性配比:比如 shared_buffers 至少要达到 max_connections / 4 * 16mb 左右(具体看版本),否则直接拒绝启动;更隐蔽的是系统级限制——linux 的 ulimit -n(文件描述符上限)必须 ≥ max_connections + reserved_connections + 一些后台进程开销,否则日志里只报 out of memory 或静默失败。
- 修改前先算:假设设
max_connections = 500,shared_buffers建议 ≥128MB(别死守文档公式,实测 64MB 在小内存机器上也可能崩) - 用
ulimit -n查当前限制,临时提可用ulimit -n 65536,永久改需编辑/etc/security/limits.conf加postgres soft nofile 65536 - 改完
postgresql.conf必须重启服务(pg_reload_conf()不生效),别信“热重载支持所有参数”这种过时说法
MySQL 的 max_connections 被 wait_timeout 和连接池悄悄吃掉
明明 max_connections = 1000,监控显示活跃连接才 200,却频繁报 Too many connections——八成是空闲连接没及时释放。MySQL 默认 wait_timeout = 28800(8 小时),如果应用层不显式 CLOSE 或连接池配置激进(比如 HikariCP 的 maximumPoolSize 设太高),大量连接卡在 “Sleep” 状态占着坑位。
- 查真实占用:
SHOW PROCESSLIST重点看Command = Sleep且Time超过 300 秒的连接 - 调低超时:
wait_timeout = 300和interactive_timeout = 300(注意:改完只影响新连接) - 应用侧必须配连接池的
idleTimeout(如 HikariCP 的idle-timeout),且值要略小于 MySQL 的wait_timeout,否则池子会往已断开的连接发请求
Python 多进程场景下 max_connections 是每个子进程独立算的
用 multiprocessing.Process 或 concurrent.futures.ProcessPoolExecutor 启了 8 个 worker,每个都连 PostgreSQL,结果数据库瞬间爆满——因为每个子进程都按配置里的 max_connections 单独申请连接,8 × 100 = 800 连接全打到 DB 上。这不是数据库配少了,是架构没对齐。
- 别让每个 worker 自己建连接池,改用父进程预建连接并传递(注意:PostgreSQL 连接不能跨进程共享,得用
psycopg2.pool的ThreadedConnectionPool替代,或换asyncpg配合asyncio) - 更稳的路:把数据库访问抽成单独服务(HTTP/gRPC),worker 全走 API,连接数由服务端统一控
- 如果非要用多进程直连,务必在
postgresql.conf里把max_connections设为worker 数 × 单 worker 预估峰值连接数 × 1.5(留缓冲)
连接数调太高反而拖慢响应?留意 work_mem 和锁竞争
盲目把 max_connections 拉到 2000,发现简单查询变慢、CPU 持续 90%——高并发下每个连接都会分到一份 work_mem(用于排序、哈希等),总内存可能远超物理 RAM;同时更多连接意味着更多锁等待、WAL 写放大、甚至 bgwriter 压力暴增。
- 观察
pg_stat_activity里state = active的比例,长期低于 10% 说明连接数严重过剩 - 调
work_mem要同步压:比如从4MB降到2MB,能减少一半内存压力(但注意:太小会导致磁盘临时文件增多) - 用
pg_locks查锁等待链,连接数上去后AccessExclusiveLock等待时间突增,就得优化事务粒度或加索引,而不是再加连接
真正卡住连接数的,往往不是配置项本身,而是 ulimit、连接池行为、进程模型这三层暗线。改之前先跑通 SELECT COUNT(*) FROM pg_stat_activity 和 cat /proc/$(pgrep postgres)/limits | grep "Max open files",数据比直觉靠谱。

















