当前位置: 首页 > news >正文

解决postgresql连接数不足

连接数不足是PostgreSQL运维中最常见的性能瓶颈之一。当客户端报错FATAL: remaining connection slots are reserved for non-replication superuser connections时,意味着数据库已无法承载新请求。本文将从紧急处置、参数调优、连接池技术、内存优化、架构设计五个层面展开解决方案,并附实操代码示例。


一、问题根源:为什么连接数会爆?
  1. 硬件/配置限制

    • 每个PostgreSQL连接消耗约10MB内存,默认max_connections=100,超限即拒绝新连接。
    • 长事务、锁竞争或慢查询导致连接长时间占用不释放。
  2. 连接泄漏

    • 应用层未正确关闭数据库连接(如PHP脚本异常退出、Java连接池配置错误)。
    • 网络闪断导致TCP半开连接(需配置tcp_keepalives_idle=60)。

二、紧急救火:快速释放连接

适用场景:生产环境突发连接阻塞,需立即恢复服务。

-- 1. 查看当前连接与占用进程 
SELECT * FROM pg_stat_activity;-- 2. 终止非关键进程 (替换$PID)
SELECT pg_terminate_backend($PID);-- 3. 阿里云/腾讯云用户可通过控制台一键清理 

风险提示:避免终止复制或核心事务进程!建议优先终止state='idle'的空闲连接。


三、参数调优:根治连接数瓶颈

核心配置(修改postgresql.conf后需重启):

# 提升最大连接数 (根据内存调整)
max_connections = 500  # 默认100,建议不超过1000# 自动清理空闲连接 (避免长时间占用)
idle_in_transaction_session_timeout = 10min  # 自动终止空闲事务# 启用TCP Keepalive防僵尸连接 
tcp_keepalives_idle = 60      # 60秒无活动发起探测
tcp_keepalives_interval = 10  # 探测间隔
tcp_keepalives_count = 10     # 探测失败次数

内存换算公式

所需内存 ≈ max_connections × (work_mem + temp_buffers + 10MB)

若内存不足,需同步调低work_mem(如32MB→16MB)。


四、连接池:低成本应对高并发的银弹 📌

为什么需要连接池?

  • 直接连接:每个请求独占一个DB连接,max_connections极易触顶。
  • 连接池模式:应用层连接池(如C3P0) → 中间件连接池(推荐) → DB连接复用。

推荐方案

  1. PgBouncer(轻量级)
    # 配置连接池模式 (transaction/pool/session)
    pool_mode = transaction  # 事务结束即释放连接
    max_client_conn = 2000   # 客户端连接数
    default_pool_size = 50   # 每个DB连接池大小
    
  2. Pgpool-II(支持读写分离)
    connection_cache = on
    num_init_children = 200   # 子进程数
    max_pool = 4              # 每个子进程连接池大小
    

实测效果:当连接池大小为50时,可支撑2000+应用线程,TPS提升4倍。


五、内存优化:节省连接资源的黑科技
  1. 启用Huge Pages
    • 减少PageTable内存占用(尤其连接数>500时)
    # postgresql.conf
    huge_pages = try  
    
  2. 监控与防OOM
    • 使用pg_top实时查看连接内存占用
    • 设置cgroup限制PostgreSQL内存

六、架构升级:分布式方案应对百万连接

当单机连接数突破2000时,应考虑:

  1. 读写分离
    • 用Pgpool或HAProxy分流读请求。
  2. 分库分表
    • Citus扩展实现水平分片。
  3. 连接卸载
    • 将计算逻辑下推至应用层(如PL/Python)。

http://www.lryc.cn/news/598803.html

相关文章:

  • 五分钟了解Java 中的锁
  • SQL基础⑪ | 约束
  • JavaScript 中的 structuredClone() 如何彻底改变你的对象复制方式
  • Android LiveData 全面解析:原理、使用与最佳实践
  • Windows 10 远程桌面(RDP)防暴力破解脚本
  • Android 与 Windows 文件路径的设计差异
  • Android Camera createCaptureSession
  • 教程:如何通过代理服务在国内高效使用 Claude API 并集成到 VSCode
  • DGMR压缩技术:让大规模视觉Transformer模型体积减半而性能不减
  • FastAPI中间件
  • iview 部分用法
  • 锁定锁存器 | 原理 / 应用 / 时序
  • 哈希表模拟实现
  • JVM 垃圾收集器CMS和G1
  • HTTP性能优化实战:从协议到工具的全面加速指南
  • 服务端对接 HTTP 接口传输图片 采用base64还是 multipart/form-data
  • 排序初识(上)-- 讲解超详细
  • Android Studio历史版本快速下载(二次修改记录)
  • rna_seq_pipeline.py-python002
  • CloudComPy使用PyInstaller打包后报错解决方案
  • 如何使用 pdfMake 中文字体
  • 【Oracle APEX 】示例应用库无法访问
  • 对称密码算法详解:从DES到AES的加密演进
  • Lua协同程序(coroutine)
  • C11补充
  • 力扣20:有效的括号
  • VirtualBox安装Ubuntu 22.04后终端无法打开的解决方案
  • 在 Ubuntu 20.04 上轻松安装和使用中文输入法
  • 离线进行apt安装的过程(在只能本地传输的ubuntu主机上使用apt安装)
  • 秋叶sd-webui频繁出现生成后无反应的问题