努力
加油

云服务器ECS上数据库连接数短时间内大幅上升怎么办?

云服务器 ECS 上数据库连接数(Connections)短时间内飙升,这通常不是“数据库坏了”,而是“应用层”或“网络层”出现了异常。作为运维或开发,遇到这种情况别慌,按以下逻辑层层剥离,基本能定位到根因。

第一步:确认是“真连接”还是“假活跃”

首先,你要区分清楚你看到的 Threads_connected 和 Threads_running 的区别。

  • Threads_connected:当前建立的 TCP 连接总数。
  • Threads_running:当前正在执行查询、未释放的连接数。

如果 Threads_connected 很高,但 Threads_running 很低,说明大量连接处于空闲状态(Idle)。这通常是连接池配置不当或连接泄漏导致的,而不是性能瓶颈。如果两者都高,那才是真的在扛流量或者卡死了。

第二步:排查最常见的三个“元凶”

1. 应用侧连接池泄露(最常见)

这是 80% 以上案例的根源。你的 Java/Go/Python 等应用使用了连接池(如 HikariCP, Druid, DBPool 等),但代码中获取了连接后,没有在 finally 块或上下文结束前正确 close() 或归还给池子。

  • 现象:连接数随时间线性增长,直到达到数据库最大限制,随后应用报错 Too many connections。
  • 验证方法:
    • 查看应用日志,是否有大量的 SQL 执行超时或连接获取失败日志。
    • 在应用服务器上使用 netstat -anp | grep :3306 (MySQL) 或对应端口,观察连接状态。如果看到大量 TIME_WAIT 或 CLOSE_WAIT,且进程 ID 指向你的应用服务,那就是连接没关干净。
    • 注意:如果是 Nginx XX数据库,检查 Nginx 的后端连接是否也堆积。

2. 慢查询导致连接堆积

一个慢查询可能占用连接几秒钟甚至几分钟。如果并发请求量大,每个请求都触发慢查询,连接数会瞬间打满。

  • 现象:Threads_running 居高不下,CPU 或 IO 负载升高。
  • 验证方法:
    • 开启 MySQL 的 slow_query_log,设置阈值极低(如 0.1s 或 1s),抓取当时的慢 SQL。
    • 使用 SHOW FULL PROCESSLIST; 命令,重点看 State 列。如果出现 Sending data, Sorting result, Locked 等状态,说明有阻塞。
    • 结合阿里云 RDS/云数据库的控制台监控,查看 QPS 和 TPS 曲线,是否与连接数峰值重合。

3. DDoS 攻击或恶意扫描

不要忽略安全层面。如果连接数突然从几百飙升至几万,且来源 IP 分散,可能是遭遇了 SYN Flood 或针对数据库端口的暴力破解/扫描。

  • 现象:连接来源 IP 杂乱无章,非业务时段突增,应用无明显流量增加。
  • 验证方法:
    • 检查安全组(Security Group)和防火墙策略。
    • 查看 ECS 的安全事件中心或云盾 WAF 日志。
    • 使用 tcpdump 抓包分析源 IP 分布。

第三步:应急处理与长效优化方案

紧急止血(短期)

  1. 切断异常源:如果是特定应用实例的问题,先重启该实例的应用服务(注意:重启会断开现有连接,需确保有重试机制,避免雪崩)。
  2. 清理空闲连接:
    • 如果是 MySQL,可以定期执行 KILL CONNECTION id; 杀掉长时间空闲的连接。
    • 更优雅的方式是在应用侧配置连接池的 maxLifetime 和 idleTimeout,强制回收陈旧连接。
  3. 临时扩容:如果确实是业务高峰(如大促),考虑临时升级数据库规格(提升 max_connections 上限),但这只是权宜之计,治标不治本。

根本解决(长期)

  1. 优化连接池配置:
    • Java (HikariCP): 设置合理的 maximumPoolSize。公式参考:CPU核数 * 2 + 磁盘数。不要设得过大,否则上下文切换开销巨大。
    • 关键参数:确保 connectionTimeout、idleTimeout、maxLifetime 合理设置。特别是 maxLifetime,建议设置为比数据库 wait_timeout 稍短的值,防止应用持有已失效的连接。
  2. SQL 优化:
    • 对慢查询进行索引优化。
    • 避免在事务中进行远程调用、文件 IO 等非数据库操作。
    • 引入读写分离,将读压力分流到只读实例。
  3. 架构升级:引入 Proxy 中间件:
    • 对于高并发场景,建议在应用和数据库之间加一层 Proxy(如阿里云 DRDS、ShardingSphere-Proxy、MyCat 等)。
    • Proxy 可以管理连接池,应用方只需保持少量长连接,由 Proxy 负责与后端数据库的多路复用。这样即使应用并发量翻倍,后端数据库的连接数也不会线性增长。
  4. 监控告警前置:
    • 不要等连接数爆了才报警。设置阈值告警,例如:当 Threads_connected 超过 max_connections 的 70% 时,立即通知开发人员。
    • 监控维度要细化:不仅看总量,还要看各应用实例的连接分布,快速定位是哪台机器出了问题。

总结

连接数飙升本质是资源供需失衡。

  • 如果是偶发,查慢 SQL 和网络抖动。
  • 如果是持续上涨,查代码连接泄漏。
  • 如果是突发海量,查攻击或流量洪峰。

记住,数据库不是用来做连接管理的,把连接管理交给应用层的连接池或专业的 Proxy 中间件,才是正确的架构思路。