服务器与大带宽专家 · 持牌IDC/CDN/ISP服务商
简米科技官网JIANMI TECH
资讯 2026-09-03 更新于 2026-09-03 简米科技 3,959 字 9 分钟阅读

数据库连接数被打满怎么办,代理层限流收敛方案

导读数据库连接数被打满时,最有效的急救动作是在应用与数据库之间加一层代理,把大量短命连接收敛成少量长连接,再按阈值做限流,让数据库永远有呼吸的余量,很多团队第一次遇到连接数告警,第一反应是扩数据库实例或者调大连接数上限,结果数据库CPU没涨多少,连接数先冲顶,应用层报“Too many connections”,整……

数据库连接数被打满时,最有效的急救动作是在应用与数据库之间加一层代理,把大量短命连接收敛成少量长连接,再按阈值做限流,让数据库永远有呼吸的余量。

很多团队第一次遇到连接数告警,第一反应是扩数据库实例或者调大连接数上限,结果数据库CPU没涨多少,连接数先冲顶,应用层报“Too many connections”,整个服务像被掐住喉咙,真正该做的事,是让连接请求在到达数据库之前,先经过一道闸门。

数据库连接数被打满的典型场景与直接后果

应用实例扩容反而加剧连接风暴

微服务架构下,每个应用实例都会初始化自己的连接池,假设一个服务有50个实例,每个实例连接池配了20个连接,那对一个数据库实例的峰值连接需求就是1000,平时业务量低没问题,一到促销或流量高峰,实例自动扩容到200个,连接请求瞬间变成4000,数据库连接数被打满,往往不是某一次大查询引起的,而是实例数量乘上连接池大小的乘积超出了数据库上限。

数据库端连接数上限是硬约束

无论MySQL还是PostgreSQL,连接数都是有限资源,MySQL默认的max_connections通常是151,调整后也就几百到几千,每个连接都要占用线程栈、缓冲区、文件描述符,连接数一旦打满,新的连接请求会被直接拒绝,已经连上的会话也可能因为资源争抢变慢,业内专家指出,连接数超过阈值后,数据库性能会呈断崖式下跌,而不是线性劣化。

常见症状包括:应用日志出现“Connection refused”或“Too many connections”;数据库监控中Threads_connected曲线直线拉满;部分慢查询突然增多,因为现有连接都在排队等锁。

数据库连接数被打满怎么办:代理层收敛的核心逻辑

代理层如何复用连接

代理层(如ProxySQL、MaxScale、ShardingSphere-Proxy)就像是数据库门口的接待员,应用发的每一个连接请求,代理不会直接转给数据库,而是从自己维护的连接池里取一条空闲连接,假设代理配了100条到数据库的长连接,那么无论后面挂500个还是5000个应用实例,数据库看到的写入压力始终只有100个连接。

具体操作上,应用连接串指向代理地址,代理再转发到真实库,以ProxySQL为例,配置admin接口后,把应用账号加入mysql_users表,设置max_connections_per_host限制应用侧连接数,数据库侧则通过mysql_servers表定义后端地址,连接池大小由ProxySQL自动管理。

数据库连接数被打满怎么办,代理层限流收敛方案

等待队列与超时控制

光收敛还不够,当100条连接全部忙时,新请求不能立刻获得连接,就得排队,代理层需要设置合理的等待队列长度和超时时间,比如ProxySQL的mysql-connection_max_age、mysql-connect_timeout,以及查询超时,超时时间太短,高峰期容易误杀慢查询;太长,前端请求会堆积,行业共识认为,等待队列长度按数据库连接数的2到3倍配置,超时控制在3到5秒,既能削峰又不至于雪崩。

读写分离与连接池调优

代理层还能顺带做读写分离,把只读请求甩给从库,这样主库连接压力进一步降低,比如MaxScale配置读写分离时,需要把应用账号的路由规则设置成“读走从库,写走主库”,配合连接池复用,主库连接数能减少一大半。

对比一下直连和代理的行为:

对比项 应用直连数据库 代理层收敛
连接总数 实例数×池大小,易爆炸 固定为代理到库的连接数
限流能力 数据库侧硬拒绝 代理侧排队+超时+熔断
运维干预 改连接数要重启应用 改代理配置热加载
故障隔离 单个应用连不上库 代理可屏蔽故障实例

数据库连接池满了如何限流:三种代理层策略

基于连接数的硬限流

这是最直接的做法,在代理层设置到后端数据库的最大连接数,超过就拒绝或排队,以ProxySQL为例,在mysql_servers表里可以给每个后端库设置max_connections字段,比如给主库设200,如果代理管理的后端连接数已达200,后续新连接会被放入队列或直接报错。

硬限流的缺点是可能误杀正常请求,所以建议配合应用端熔断,比如在应用侧捕获ConnectionException后快速失败,而不是无限重试。

基于请求速率的软限流

比连接数更精细的是按请求速率限流,代理层每秒能转发多少个查询,这个阈值可以动态调整,ShardingSphere-Proxy的SQL执行引擎支持在每个逻辑库上配置maxConnectionsSizePerQuery,但更推荐用流量治理插件,比如在代理层做令牌桶,平均每秒允许1000次查询,超过的请求先缓存,缓存满了返回“系统繁忙”。

数据库连接数被打满怎么办,代理层限流收敛方案

软限流适合读多写少的场景,比如一个电商商品详情页,缓存失效瞬间有上万次请求打到数据库,代理层用速率限流把前500毫秒的请求控制在数据库能承受的范围,后面的请求在应用层直接降级返回默认数据。

基于慢查询的熔断降级

连接数被打满往往伴随一堆慢查询,代理层可以设置慢查询阈值,比如超过2秒的SQL直接切断,并记录到日志,ProxySQL有mysql_query_rules机制,可以按digest匹配SQL指纹,给特定SQL设置timeout。

实操中,打开ProxySQL的stats_mysql_query_digest表,找出消耗时间最长的top SQL,然后针对这条SQL设置规则:

INSERT INTO mysql_query_rules (rule_id, active, digest, timeout, flagIN, flagOUT) VALUES (10, 1, '0x3F1A...', 2000);
LOAD MYSQL QUERY RULES TO RUN;
SAVE MYSQL QUERY RULES TO DISK;

这样超过2秒的相同SQL会被强制中止,释放连接。

代理层选型与部署要点

自建代理与云数据库代理的取舍

自建ProxySQL、MaxScale等开源方案,部署成本低,但需要自己维护高可用,云数据库大多自带代理,比如简米云的数据库代理、酷番云的TProxy,价格按规格或连接数计费,不少用户关心“代理层做限流价格贵不贵”,实际对比下来,自建一台2核4G的ECS跑ProxySQL,能支撑几百个连接转发,云数据库代理则按小时计费,适合不想自己运维的团队。

选型时重点看三点:是否支持透明接入(应用零改动)、是否具备连接池复用、是否能热更新规则,ProxySQL的配置修改后不需要重启,MaxScale也支持动态修改。

代理层本身会不会成为新瓶颈

加了代理,多一跳网络开销,本地机房里代理与应用之间的时延通常小于1毫秒,对业务影响可忽略,代理层自身要配置高可用,至少两个节点做VIP漂移,另外代理的内存要足够,因为每个连接的buffer都会占内存,一个代理节点建议预留2GB以上的内存空间来缓冲排队请求。

部署顺序建议先灰度:让一个非核心服务切到代理,观察连接数曲线和耗时是否平稳,再全量切换,如果云上环境,优先用云厂商的代理产品,因为它们通常已经做了内核级优化,并和监控告警打通。

数据库连接数被打满怎么办,代理层限流收敛方案

代理层限流之外的兜底手段

应用侧连接池参数调优

代理层挡在前面,应用侧也不能完全放飞,常见的连接池HikariCP里,minimumIdlemaximumPoolSize要按实际并发设置,不是越大越好,一个服务实例的maximumPoolSize设置为10就足够应对多数场景,因为单个SQL执行不到几十毫秒,把maximumPoolSize从50降到10,应用侧能少创建大量空闲连接,也减轻代理的压力。

同时打开connectionTimeoutvalidationTimeout,如果数据库长时间无响应,连接池能快速淘汰坏连接,避免应用线程全部卡死。

监控告警与快速扩容

代理层把连接数管住了,但业务量持续上涨时还是要扩容,监控项至少包含:代理到后端的活跃连接数、等待队列长度、前端请求拒绝次数,当等待队列持续超过1秒时,说明限流阈值太低,需要提升代理节点规格或增加后端库,不少团队在数据库监控里专门建一条“代理层活跃连接数”的曲线,一旦超过设置的80%,就触发扩容流程。

数据库连接数被打满时代理层限流Q&A

代理层限流和数据库连接池限制有什么区别?

数据库连接池限制只能管单个应用实例内部的连接数量,多个实例各自为政,加起来仍可能打满数据库,代理层限流是全局视角,不管后面挂多少个应用,代理统一控制到数据库的总连接数,而且能排队、超时、熔断。

用代理层后应用连接串要怎么改?

把原来的数据库IP端口改为代理的IP端口,账号密码不变,如果代理支持多端口,可以在一个代理实例上区分读写流量,改完后测试一下长连接和短连接场景,确认代理的等待队列参数已生效。

代理层限流会影响正常业务吗?

会有极短暂的影响,但远比数据库崩溃好,限流触发时,部分请求会多等几百毫秒,如果等待超时则返回错误,应用侧配合重试或降级即可,多数情况下,合理的代理层限流能把可用性从几乎为零拉回一个可接受的高度,比如高峰期保持小比例的请求失败,而不是所有请求全部超时。

连接数被打满不是数据库的问题,是接入层缺少管控,代理层做收敛和限流,相当于给数据库装了一个安全阀,先让连接数可控,再去优化SQL和缓存,这条路比抱着数据库硬扛要稳得多。

分享本文
本文为 简米科技官网 原创,已由运维技术专家审核。转载请注明来源:原文链接
售前咨询 服务热线 售后 邮箱