数据库连接数被打满怎么紧急扩容
摘要:# 数据库快被“撑爆”了?别慌,手把手教你紧急扩容 那天下午,我们技术群里突然炸了锅。一个核心业务系统的后台监控全红了,告警短信像催命符一样响个不停。点开一看,数据库连接数曲线图,不是“缓慢上升”,而是像坐火箭一样“砰”地一声撞到了天花板。前端页面一片“…
数据库快被“撑爆”了?别慌,手把手教你紧急扩容
那天下午,我们技术群里突然炸了锅。一个核心业务系统的后台监控全红了,告警短信像催命符一样响个不停。点开一看,数据库连接数曲线图,不是“缓慢上升”,而是像坐火箭一样“砰”地一声撞到了天花板。前端页面一片“服务不可用”,运营同事的电话直接打到了技术负责人手机上。
说白了,这就是一次典型的数据库连接数被打满的线上事故。 那种感觉,就像早高峰的地铁1号线,闸机口已经挤满了人,但后面还有源源不断的人流涌来,最终系统彻底“卡死”,谁也进不去。
如果你没经历过,可能觉得“扩容”两个字敲敲键盘就行。但真到了火烧眉毛的时候,你会发现很多“教科书方案”根本来不及用。今天,我就结合自己踩过的坑和救过的火,跟你聊聊怎么在几分钟到半小时内,把数据库从“窒息”边缘拉回来。
一、先保命:立刻“止血”,别让业务彻底停摆
记住,紧急处理的第一原则不是根治,而是先让业务能转起来。 这时候别想着什么优雅的解决方案了。
-
火速重启应用?慎重! 这是最直接但也最危险的一招。很多人的第一反应是重启应用服务器,释放所有连接。但你想过没有,如果根本原因是慢查询或者死锁,重启后海量请求瞬间重连,很可能在几秒内再次打满,形成“重启-打满-再重启”的死循环。(我自己就干过这种傻事,结果让故障时间延长了一倍。)
-
紧急“杀连接”:快准狠的物理手段 这才是真正的“止血钳”。立刻登录数据库,执行查看和杀死非核心空闲连接的命令。
- MySQL: 先用
SHOW PROCESSLIST;找出所有连接,重点关注Command是Sleep且时间过长的,以及那些明显在执行慢查询的。然后果断用KILL [connection_id];干掉它们。优先杀那些来自报表查询、后台任务的连接。 - PostgreSQL: 使用
SELECT * FROM pg_stat_activity;查看,然后用SELECT pg_terminate_backend(pid);终止进程。 大实话: 这个过程心里肯定在滴血,因为你不知道杀掉的哪个连接会影响到某个正在进行的用户订单。但两害相权取其轻,让80%的用户能访问,总比100%的用户都卡死强。
- MySQL: 先用
-
火线调整应用配置 同时,让运维同学立刻修改应用(如Java应用)的数据库连接池配置(比如Druid、HikariCP),临时调低
maxActive(最大连接数)。这听起来反直觉,但目的是控制应用“出血”的速度,为后续扩容争取时间。相当于把地铁闸机临时关小一点,虽然排队更长,但至少不会让站内彻底崩溃。
二、找病根:连接数为什么突然爆了?
一边“止血”,一边必须马上找原因。连接数打满通常不是数据库的错,而是“猪队友”造成的。就我见过的案例,无非这么几类:
- 慢查询泛滥(最常见): 某个没加索引的SQL突然被大量调用,或者缓存失效导致所有请求直接怼到数据库。(感觉就像突然所有人都要去同一个窗口办业务,队伍不长才怪。)
- 连接泄漏(最隐蔽): 应用代码里拿了数据库连接,用完了没关,或者异常处理不当没还回去。连接池里的连接用一根少一根,最后耗尽。
- 流量洪峰(最直接): 遇到突发营销活动或热点事件,真实流量远超预估。这种反而“病因”单纯,就是准备不足。
- 数据库自身问题: 比如锁等待严重,事务长时间不提交,占用着连接不释放。
怎么快速定位? 别光看数据库监控,立刻去查应用日志和APM工具(比如Arthas、SkyWalking),看看是不是有某条SQL的调用量或耗时曲线异常陡增。十有八九就是它了。
三、真扩容:不只是“加机器”那么简单
找到原因并暂时控制住局面后,我们才真正进入“扩容”环节。这里的扩容,是广义的,目的是快速提升数据库的“并发消化能力”。
方案A:垂直扩容(给数据库“打鸡血”)——最快,但也最贵
- 做什么: 在云平台上,直接给你的数据库实例升配。比如阿里云RDS,从4核8G升级到16核32G,把最大连接数参数(如
max_connections)调大。 - 优点: 快! 通常几分钟到十几分钟就能完成,而且对应用几乎透明,改个配置就行。
- 缺点: 烧钱。而且有物理上限,不可能无限升级。这属于“金钱换时间”的紧急通道。
- 个人建议: 如果故障发生在深夜或者业务关键期,别犹豫,先花钱买时间。事后再慢慢研究怎么优化降配。
方案B:水平扩容(给数据库“找帮手”)——治本,但需要设计
这个需要一点前期准备,但如果你的系统经常被连接数问题困扰,真的值得考虑。
- 读写分离: 这是缓解连接压力立竿见影的方法。立刻配置一个或多个只读从库,把所有的查询请求(比如报表、搜索、用户非核心页面)全部引流到从库。主库只处理写操作和核心读事务。一下子就把主库的连接压力砍掉一大半。 很多云数据库控制台点几下就能配好。
- 连接池中间件: 上MyCat、ShardingSphere这类中间件。它们本身可以管理一个大的数据库连接池,应用连接到中间件,由中间件来负责和多个数据库实例打交道,并对连接进行复用和管理。这相当于在应用和数据库之间加了一个“缓冲池”和“调度员”。
- 紧急分库分表?别闹! 说真的,在故障发生时现场搞分库分表,基本等于宣布系统“死刑缓期执行”。 这玩意儿是架构级改造,没充分设计和测试,上去就是新灾难。但它必须是事后的重点优化方向。
方案C:应用层“减压”(不花钱的智慧)——立刻就能做
这才是体现工程师功力的地方,而且很多措施能立刻生效。
- 疯狂加缓存: 对导致慢查询的热点数据,比如用户信息、商品详情,不管用Redis还是Memcached,立刻给它套上缓存。(记住,最快的数据库查询,就是不查数据库。)
- SQL限流与降级: 在应用或中间件层,对识别出的问题SQL进行限流。比如,每秒只允许执行100次,超过的请求直接返回降级内容(如默认值、排队提示)。这虽然影响部分用户体验,但保住了系统大盘。
- 优化连接池参数: 别小看这个。检查你的
validationQuery(连接有效性检测语句)是不是太慢?testOnBorrow(借出时检测)会不会太频繁?不合理的配置会白白消耗连接资源。
四、事后复盘:别让同样的火再烧一次
故障恢复后,千万别当没事发生。必须复盘,而且要从根上解决问题:
- 建立连接数监控告警: 别等打满了再报。设定80%使用率的预警线,提前介入。
- 定期进行慢查询分析与优化: 把这变成日常功课,而不是救火后的忏悔。
- 完善压测与预案: 下次大促前,老老实实用全链路压测摸清数据库的底线。把上面提到的各种扩容、限流、降级方案写成可执行的应急预案。
- 代码审查: 重点查数据库连接关闭的逻辑,用静态扫描工具找找有没有泄露的风险。
最后说句实在的, 数据库连接数被打满,就像一次系统的高烧。紧急扩容是退烧针,能让你从ICU里出来,但要想身体强健,还得靠日常的架构锻炼、代码素养和监控体检。别等下次再被“打满”了才想起来要“扩容”。
行了,思路就聊这么多。真遇到事儿了,冷静点,按步骤来,问题总能解决的。

