问问助手

连接数一满,全站排队:连接池该开多大

2026-10-24 Aryee 1
连接数一满,全站排队:连接池该开多大

连接数一满,全站排队:连接池该开多大

一、先看一个具体的下午

下午三点,促销刚开始十分钟。商品页还能打开,点结算一直转圈。

客服那边,客户在问同一句话:是不是你们的系统又坏了。

运维先看数据库,处理器占用不高,磁盘也不忙。再看连接数,已经顶到上限。应用日志里出现一排等待连接超时。

老板说,加机器。运维加了两台应用服务器,页面没有变快,数据库连接更快满了。

这个画面很常见。问题不在应用算不过来,而在数据库的连接名额已经用光。

二、连接不是免费的

每一个数据库连接,数据库都要分出一份内存和一套会话状态。

PostgreSQL 常见做法是一个连接对应一个后台进程,即使闲着也占内存。MySQL 是一个连接对应一个线程,还要配自己的缓冲区。

所以数据库的连接上限,不是随便调大的一个数字。它背后是内存、进程或线程,以及切换开销。上限调得越高,数据库在同样硬件上能留给查询的资源越少。

PostgreSQL 的常见缺省值是 100,MySQL 8.0 是 151。很多团队从没改过,直到某天连接被占满才发现。

三、先分清三种排队

连接被占满时,请求不一定卡在同一个地方。

第一种,应用自己的连接池满了,请求在池子里等一条空闲连接。

第二种,应用连的是连接代理,代理到数据库的连接满了,请求在代理里等。

第三种,数据库的连接名额用光了,新连接直接被拒。

三种排队看起来都是页面慢,处理办法完全不同。先看等待发生在哪一层,再谈加不加机器。

四、一个乘法:实例数乘每实例池大小

应用侧最关键的数,不是一个池子开多大,而是全站一共能开多少条。

算法很直接:在线实例数,乘每个实例的连接池上限,再加上后台任务、定时任务、数据迁移、报表和运维工具各自占用的连接。

比如数据库允许 200 条连接,20 个应用实例、每个池子开 20 条,光应用就要 400 条。上线第一天就会有一半请求在池子里等。

如果把每个池子调到 50 条,20 个实例就是 1000 条。数据库那边不会因为池子数字变大,就多出名额。

五、为什么加机器有时反而更快打满

高峰期应用扛不住,最常见的动作是扩容。每起一个新实例,它就按配置建一套自己的连接池。

流量涨一倍,实例数也涨一倍,连接需求跟着涨一倍。数据库的连接名额没有变,反而在它最忙的时候被更多空闲连接占住。

所以会出现一个反直觉的画面:应用机器加了,数据库连接更快满了,页面更慢。

加机器解决的是应用的计算能力,不解决数据库的连接名额。这是两个问题,要分开看。

六、无服务器把这个问题放大

函数计算这类运行方式,实例按请求起落,生命周期很短。每个实例都可能建一套自己的连接池。

流量一涨,平台会同时起很多实例。每个实例只开几条连接,加起来也可能瞬间超过数据库上限。

2026 年 10 月,一篇讲无服务器连接问题的排障文章里,把这个过程写得很清楚:实例各自建池,扩容时连接数一起冲上来,闲置实例被回收时连接又没有正常归还。

这类场景通常不适合让应用直连数据库。要么把每实例的连接数压到很小,要么在中间放一层连接代理。

七、连接泄漏:最常见的隐形占用

连接泄漏是指代码借了一条连接,用完没有还。平时看不出来,跑几天后池子慢慢被占满,重启应用又恢复。

常见来源有几个:异常分支没有关闭连接,后台任务拿到连接后去做很慢的外部调用,回调里又借了一条,或者框架版本变化后关闭方法没被执行。

排查时先看两个数:池里的活跃连接数和空闲连接数。如果业务量没涨,活跃连接却一直往上走,先怀疑泄漏,不要先调大池子。

连接池一般都有借出超时和泄漏检测,把这两项打开,日志里能看到是哪一段代码借了不还。

八、长事务和空闲事务:占着不走

还有一类占用不是泄漏,是借了之后一直不还。

有的事务开启后去等一个外部接口,等文件上传,等用户确认,甚至等一段生成内容返回。这期间它一直占着连接,别的请求只能排队。

数据库里还有一种状态叫空闲事务:事务开着,但当前没有语句在跑。它不干活,却仍然占着连接和锁。

处理办法是给事务设上限:单条查询跑多久必须停,事务空闲多久必须断。业务代码也要改,把外部调用挪到事务外面,别让一次慢调用拖住整个池子。

九、连接代理能解决什么

连接代理站在应用和数据库中间。应用连代理,代理再连数据库,很多应用连接可以共用少量数据库连接。

它主要解决两件事:连接数量,以及建连成本。应用重启或扩容时,不会每来一个实例就向数据库要一批新连接。

2026 年 1 月,OpenAI 公开过一组数:在数据库前加连接代理后,平均建连时间从 50 毫秒降到 5 毫秒。文章里也提到,此前遇到过连接风暴把可用连接一次用光。

但代理只是把连接复用起来,不会让数据库多出计算能力。它把排队的位置从数据库门口挪到了代理里,排队本身还在。

十、代理不是万能:事务模式会碰到哪些坑

连接代理常见两种工作方式:会话模式和事务模式。

会话模式下,一个应用连接从头到尾对应一条数据库连接,复用程度低,但行为最接近直连。

事务模式下,一条数据库连接只在一个事务期间归某个应用使用,事务一结束就还给代理。复用程度高,但要小心会话状态。

预编译语句、临时表、会话变量、咨询锁,这些东西在事务模式里可能跨事务丢失,也可能串到别的连接上。有些驱动和框架需要专门配置才能兼容。

所以换代理之前,要拿真实业务和真实驱动做一轮完整回归测试,不能只看一个简单查询能不能通。

十一、代理自己也会堵

代理不是一根不会堵的管子。它有自己的处理器、内存和连接上限。

2026 年 9 月,一家云厂商的排障指南把两种故障分开写:一种是连接池耗尽,活跃连接顶到上限,等待的客户端越来越多;另一种是连接池软件自己饱和,数据库那边的连接数并不高,但代理这一层已经排起长队。

指南里还提到,常用的 PgBouncer 单个进程只用一个处理器核心。数据库再大,代理这一层也可能先到瓶颈。

所以代理要么按流量配足规格,要么横向多起几个实例,并且把代理自己的等待队列和处理器占用放进监控。

十二、MySQL 和 PostgreSQL 的差别

两种数据库的连接代价不一样。

PostgreSQL 一个连接通常对应一个后台进程,连接数上去后,内存和进程切换的压力更明显。MySQL 一个连接对应一个线程,缺省上限通常更高一些,但每个连接也有自己的缓冲区和内存开销。

云上的托管数据库还会在服务商那边再加一层限制,实际能用的连接数可能比参数表上写的少。备份、监控、复制和运维账号也会占掉一部分。

所以不要把一种数据库的调优数字直接搬到另一种上。先读清楚当前实例的真实上限和保留名额。

十三、该看的四个数

连接问题最怕的是只看数据库处理器占用。处理器不高,不代表连接没满。

第一,数据库的连接上限和当前连接数。要知道还剩多少名额,而不是只知道有没有报错。

第二,应用连接池的活跃数、空闲数和等待数。等待数连续几分钟大于零,就说明池子已经不够用。

第三,代理的客户端连接数、到数据库的连接数和等待队列。代理两侧要分开看。

第四,最长事务时长和最长空闲事务时长。这两个数能提前暴露慢调用和忘记提交。

这四个数放在同一块屏幕上,值班的人才知道该找应用、找代理,还是找数据库。

十四、池子该开多大:从业务能等多久倒推

不要从「池子默认 20,先调到 50」开始。要从数据库的名额往下算。

先扣掉不能给业务的那些:管理员账号、复制、备份任务、监控与迁移工具,再留出两成到三成的余量,防止突发和故障倒换。剩下的才是应用能用的总额。

用这个总额除以最大实例数,得到每个实例的池子上限。注意是最大实例数,不是平时的实例数。自动扩容会把实例数拉高。

再往下才是业务能等多久。如果池子里排队的时间已经超过页面能接受的等待,调大池子只是把压力往后推。要么加代理提高复用,要么加数据库名额,要么把慢查询和长事务先处理掉。

十五、一张表:按现状先做哪一步

你的现状 先做哪一步 主要代价
实例不多,连接总数离上限还远 给每个池子设上限,打开泄漏检测 配置要对齐,扩容时要重算
实例数在涨,连接总数接近上限 先压小每实例池子,再评估连接代理 代理要多一层部署和监控
流量按请求起落,实例数变化大 上连接代理,应用侧只留很小的池子 事务模式要回归,代理自己要扩容
在线和跑批共用一个库 给跑批单独限流,挪到低峰 报表会晚一些出来
连接已经打满 先结束空闲和长事务,再上代理,最后才加数据库规格 前两步只能缓一阵,加规格最贵

十六、上线前要验四件事

第一,按峰值的一点五倍压一轮,盯住池子等待数和借出超时数。只看平均响应时间会漏掉排队。

第二,代理出问题时应用要快速失败,不能无限等。连接超时和重试次数要设上限,重试要带退避和随机抖动,避免所有实例同时再冲一次。

第三,数据库重启或主备倒换后,应用会同时重连。要验证这一下不会把刚恢复的数据库再压死。池子要能预热,重连要有节奏。

第四,监控和告警要能看到前面那四个数,并且写清楚谁负责调。连接数是一个全站共享的额度,不能每个团队各调各的。

十七、三个自查问题与这一轮的决定

第一,全站最多能开多少条连接,这个数谁算过,写在哪。答不出来,说明容量还没有人负责。

第二,池子里等的时间,能不能在屏幕上看到。只看到处理器占用,等于闭着眼睛开车。

第三,数据库重启一次,应用会不会一起把它再压死。如果会,先改重连和重试,再谈扩容。

多数团队第一步不是换更大的数据库,而是把池子上限、泄漏和长事务这三件事处理掉。连接代理是下一步,加数据库规格是最后一步。

顺序反过来,钱花了,排队还在。

你手上那套系统,卡在哪一步?

留个手机号和方便的时间,我打过来先听你说现状和限制,再给一个能执行的判断:这套系统该继续修、该动哪里,还是重做一版更省。

约一次沟通不接纯 UI 外包,只做系统层面的问题。不方便留号码,也可以直接跟助手说一句话。