springboot应用即使使用了连接池,MySQL数据库仍然有大量sleep状态的连接

springboot应用即使使用了连接池,MySQL数据库仍然有大量sleep状态的连接

  • 问题背景
  • 概念理解
    • MySQL配置参数wait_timeout概念
    • Hikari配置参数(项目使用hikari作为数据库连接池)
  • 实践出真知
  • 总结和解决思路

问题背景

近期客户生产环境报:查询数据库发现有大量sleep的连接(800多个),询问为什么不关闭这些没用的连接。这里说明一下,生产环境的业务量还是很大的,每分钟有几千的并发。
sleep连接过多会造成的影响(这里搬运ai的回答):

  1. 内存消耗(主要影响)
    Sleep 连接本身 不消耗 CPU,但会占用 线程 ID 和 文件描述符(FD)。如果系统 max_connections 较高(如默认 151),890 个 Sleep 连接可能导致:新连接被拒绝(Too many connections 错误)。
    线程切换开销增加(尤其在并发高的场景)。
  2. CPU 和线程调度
    Sleep 连接本身 不消耗 CPU,但会占用 线程 ID 和 文件描述符(FD)。如果系统 max_connections 较高(如默认 151),890 个 Sleep 连接可能导致:新连接被拒绝(Too many connections 错误)。
    线程切换开销增加(尤其在并发高的场景)。
  3. 其他资源
    文件描述符(FD):每个连接占用 1 个 FD,可能耗尽系统限制(ulimit -n)。临时表/缓冲区:某些后台操作(如临时表、排序缓冲区)可能因连接数过多而竞争资源。

概念理解

MySQL配置参数wait_timeout概念

定义:MySQL 服务器主动关闭空闲(Sleep)连接前的等待时间(单位:秒)。
默认值:通常为 28800秒(8小时)。
作用:当一个MySQL连接在wait_timeout秒内没有任何活动时,服务器会自动关闭该连接;释放资源:通过关闭空闲连接来释放服务器资源,避免长期不用的连接占用内存和连接数。
修改方法:

-- 将 wait_timeout 缩短(需评估业务场景)
SET GLOBAL wait_timeout = 600;  -- 10分钟

Hikari配置参数(项目使用hikari作为数据库连接池)

  • connection-timeout (默认: 30000ms)
    功能:从连接池获取连接的最大等待时间
    细节:
    如果所有连接都在使用中,且池已达到maximum-pool-size,新请求将等待此超时时间超时后抛出SQLException
    设为0表示无限等待(生产环境不推荐)
  • idle-timeout (默认: 600000ms/10分钟)
    功能:空闲连接存活时间
    细节:
    超过此时间的空闲连接将被释放
    最小有效值=10000ms(10秒)
    设为0表示禁用空闲连接回收(不推荐)
  • maximum-pool-size (默认: 10)
    功能:连接池最大连接数(包括使用中和空闲连接)
    最佳实践:
    通常建议公式:
    (核心数 * 2) + 有效磁盘数
    例如4核服务器: (4*2)+1 = 9
    maximum-pool-size: 10
  • minimum-idle (默认: 与maximum-pool-size相同)
    功能:连接池保持的最小空闲连接数
    特殊场景:
    设为0表示不保留空闲连接(适合突发流量场景)
    生产环境通常设为maximum-pool-size的1/4~1/2
  • max-lifetime (默认: 1800000ms/30分钟)
    功能:连接最大存活时间(从创建到销毁)
    关键点:
    到期后连接会被销毁(即使正在使用)
    必须比数据库的wait_timeout小2-3分钟
  • keepalive-time (默认: 0/禁用)
    功能:定期对空闲连接发送保活查询(如SELECT 1)
    推荐配置:
    keepalive-time: 30000 # 每30秒保活一次

配置示例(这里给出一个参考配置)

hikari:pool-name: "prod-pool"maximum-pool-size: 20minimum-idle: 5idle-timeout: 60000max-lifetime: 1740000  # 29分钟(MySQL wait_timeout=30分钟)connection-timeout: 1000leak-detection-threshold: 5000data-source-properties:cachePrepStmts: trueprepStmtCacheSize: 500

那么MySQL数据库既配置了wait_timeout,连接又配置了idle-timeout,那么关闭数据库连接具体要以哪个为准呢?
下面是我的应用目前生产环境的hikari配置:

spring:datasource:hikari:connection-timeout: 20000idle-timeout: 120000maximum-pool-size: 200minimum-idle: 10register-mbeans: true

实践出真知

  1. 单独启动一个应用(应用内有定时任务的话先关闭,或者启动后有直接连接数据库操作的业务的话也先关闭,保持一个干净无访问的状态)
    使用下面命令查询数据库sleep的连接信息:
SELECT user, host, command, time, info FROM information_schema.processlist WHERE command = 'Sleep' ORDER BY time DESC;

在这里插入图片描述
正常情况下这里的条数应该是hikari连接池配置的minimum-idle数量(我这里多了1条不知道哪里的连接,不必理会),既hikari连接池会初始化minimum-idle设置的空闲连接,可以避免突然的并发访问带来的数据库连接消耗。
2. 并发量小使用空闲连接处理请求的情况
使用jmeter模拟20条并发访问:
在这里插入图片描述
查询sleep连接数:
在这里插入图片描述

没有变化,说明这10个空闲的连接足以处理完这20条并发请求。注意:这里的空闲连接在处理完一个请求后可以被立即继续使用用来处理其它的请求,除非所有空闲的连接都在被使用时,又有新的请求进来,这是才会去连接池建立新的连接(下面会证明)。
3. 并发量大空闲连接不够用的情况
使用jmeter模拟500条并发访问:
在这里插入图片描述
查询sleep连接数:
在这里插入图片描述

这里看到sleep的连接增加了8条,说明10个空闲连接已经不够用了
过2分钟后再查询连接数:
在这里插入图片描述

发现连接数从新变回minimum-idle。由此说明这些连接完全有hikari连接池管理,当minimum-idle的连接不够使用时会新建连接,这些连接使用完到达idle-timeout时间后由hikari主动发送关闭指令给到数据库关闭(发送 COM_QUIT 给 MySQL),然后继续维持minimum-idle的空闲连接。实际上跟MySQL设置的wait_timeout没有关系了,这是由于应用使用了连接池管理的好处,如果没有使用连接池,这些sleep的连接只能有数据库控制,到wait_timeout时间才能关闭。
4. 一些验证hikari连接池是否在应用中生效的方法(这个我没用,因为上述压测的方式已经验证它在正常运行)
(1) 添加监控代码

import com.zaxxer.hikari.HikariDataSource;@RestController
public class PoolController {@Autowiredprivate DataSource dataSource;@GetMapping("/pool-status")public String poolStatus() {if (dataSource instanceof HikariDataSource) {HikariDataSource hikari = (HikariDataSource) dataSource;return String.format("Pool: %s, Active: %d, Idle: %d, Total: %d",hikari.getPoolName(),hikari.getHikariPoolMXBean().getActiveConnections(),hikari.getHikariPoolMXBean().getIdleConnections(),hikari.getHikariPoolMXBean().getTotalConnections());}return "Not using HikariCP!";}
}

(2) 启动时打印配置
在 @PostConstruct 中输出配置:

@SpringBootApplication
public class MyApp {@Autowiredprivate DataSource dataSource;@PostConstructpublic void init() {if (dataSource instanceof HikariDataSource) {HikariConfig config = ((HikariDataSource) dataSource).getHikariConfig();System.out.println("=== HikariCP Config ===");System.out.println("jdbcUrl: " + config.getJdbcUrl());System.out.println("minIdle: " + config.getMinimumIdle());System.out.println("maxPoolSize: " + config.getMaximumPoolSize());System.out.println("idleTimeout: " + config.getIdleTimeout());}}
}

总结和解决思路

通过上述验证,可以得出系统hikari在正常运行,至于数据库还是产生大量sleep连接,只能说明系统并发量太高了。
一些想法:

  1. 先跟客户沟通看客服能否接受现在的sleep连接数,毕竟他们生产环境给到数据库的内存还是很充足的。
  2. 如果想这些sleep的连接立即关闭,可以修改连接池idle-timeout的设置,设置的小一点,如:10秒,这样连接可以很快关闭,但是不建议。试想高并发下,空闲连接是可以快速关闭,给客户一种数据库岁月静好的假象,但是业务量是实际存在的,这样每次都要频繁的关闭和创建新的连接,这个开销是非常大的,搞不好会拖垮整个系统。
  3. 优化并发量较大的系统接口,缩短每个连接的处理速度,提高复用率,这样就会少创建新的连接。具体可以从业务层面,数据库查询、索引优化等入手。
  4. 添加缓存,减少数据库的访问。把那些数据库查询频繁的操作放到缓存中,不走数据库,从根本上解决问题

一些拙见,记录下自己解决问题的一个过程,不对的地方感谢指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87271.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows下安装和使用git

本文为windows下git的下载安装和使用。 git下载和安装 参考: windows安装git(全网最详细,保姆教程)-CSDN博客 【学了就忘】Git介绍 — 4.Git的安装 - 简书 先解决下载时的一些疑惑: 选择哪个架构? 电脑ARM6…

借助工具给外语视频加双语字幕的实用指南​

给外语视频配上双语字幕,能让不同语言背景的观众更轻松理解内容,也能让视频在传播时更受欢迎。现在有不少智能工具能帮我们高效完成这项工作,比如 ViiTor AI 平台,它在处理双语字幕方面有不少实用功能,下面就结合其功能…

Claude 4 与 Gemini 2.5 Pro:开发者深度比较

Claude 4 与 Gemini 2.5 Pro:开发者深度比较 在使用相同的编码挑战对Claude Sonnet 4和Gemini 2.5 Pro Preview进行广泛的正面测试后,我发现了每个开发人员都应该了解的显著性能差异。我的发现揭示了执行速度、成本效率以及最重要的,精确执行…

怎么进入9870端口

在实验时想进入9870端口查看safe状态 但是输入localhost:9870后显示: 首先使用jps确认hadoop状态: 从 jps 的输出来看,Hadoop 的核心服务(NameNode、DataNode、ResourceManager、NodeManager 等)都已经正常运行&…

Windows、Linux、macOS 三大系统安装 Git 的常见坑点及解决方案,附带 具体操作示例,帮助新手快速避坑

以下是 Windows、Linux、macOS 三大系统安装 Git 的常见坑点及解决方案,附带 具体操作示例,帮助新手快速避坑。 一、Windows 系统安装 Git 1. 安装路径含空格或中文 坑点:默认路径 C:\Program Files\Git 可能导致某些脚本报错。 解决:自定义路径(如 D:\DevTools\Git)。…

OpenAI最新 GPT-4.1 、 GPT-4.1 mini 和 GPT-4.1 nano 新模型如何在ChatGPT付费创作系统平台对接API使用

GPT-4.1 ‌是 OpenAI 于2025年4月15日发布的最新语言模型系列,包括 GPT-4.1 、 GPT-4.1 mini 和 GPT-4.1 nano 三款新成员。这些模型在编程、指令遵循和长上下文理解方面表现出色,支持最大可达100万个Token的上下文窗口,适用于处理复杂任务和…

计算机网络(三)传输层TCP

目录 一、TCP概述​ 二、TCP三大核心特性 三、 对比UDP​​ (1)TCP、UDP对比 (2)TCP、UDP头部格式: (3)应用场景 ​ 四、TCP的三次握手、四次挥手 (1)三次握手(建…

Spring、SpringBoot 本身为什么不提供 Bean 的异步初始化

这是一个很有深度的架构问题!Spring/Spring Boot 本身为什么不直接提供 Bean 的异步初始化? 下面从原理、历史、设计哲学、技术挑战、社区现状等多个层面为你详细分析。 一、Spring Bean 初始化的默认行为 Spring IoC 容器在启动时,会同步地…

第十三节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入门 - 接口操作审计日志功能

Vben5 系列文章目录 💻 基础篇 ✅ 第一节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入门 ✅ 第二节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入门 - Python Flask 后端开发详解(附源码) ✅ 第三节:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入…

AI掌柜失守记:AI Agent商业自动化边界实验

1. 实验设计:数字掌柜接管实体货架 1.1 硬件载体与虚拟人格构建 位于旧金山的实验场地被改造成微型零售生态系统:智能冰箱搭配商品篮构成实体货架,iPad自助结账系统连接Venmo支付接口,Slack通讯平台成为人机交互窗口。Claude So…

NAT 打洞

本文基于NAT3NAT3实现upd打洞(假设你对NAT类型已经很清楚) 如果A网络的NATAB网络的NATB的值大于6则打洞会失败,需要使用turn中继服务 STUN协议解析 #pragma once #include "hv/UdpClient.h" #include "fmt/format.h" /*…

java近期工作总结

近期工作中的一些总结 (1)三层模板和流程 我发现很多东西其实吧,三层就是一个模板和流程; 正向推,从控制层开始,反向从内个sql开始写,大部分应该就是从xml文件开始的,然后写到控制层…

vue中的torefs

在 Vue 中, toRefs(state) 的返回值是一个 新对象,其中每个属性都是对应 state 中原始属性的 ref 对象。具体来说: 返回值的结构与特性 1. 对象结构 - 若输入 state 为 { a: 1, b: text } ,则 toRefs(state) 返回&a…

可编程逻辑器件的演进与对比分析

可编程逻辑器件的演进与对比分析 目录 离散逻辑芯片与早期PLD的限制CPLD的诞生与结构特点FPGA的架构创新CPLD与FPGA的核心差异总结 1. 离散逻辑芯片与早期PLD的限制 在还没有发明出可编程逻辑器件(PLD: Programmable Logic Device)之前,设…

Ubuntu机器开启root用户远程登录

一般正常情况是可以直接使用非root用户登录,但是由于权限问题,所以部分内容需要远程ROOT用户登录,具体如下: 1️⃣配置root用户密码 一般情况下系统中root不能直接登录,所以也没有保存root密码,现在需要登…

rockchip android14 设置不休眠

rockchip android14 设置不休眠 文章目录 rockchip android14 设置不休眠前言一、代码路径二、代码修改前言 在rk 的android14代码中设置开机后永不休眠 一、代码路径 device/rockchip/common/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml二、…

什么是数据孤岛?如何解决数据孤岛问题?

目录 一、数据孤岛的定义与表现 1. 数据孤岛的定义 2. 数据孤岛的表现形式 二、数据孤岛产生的原因 1. 技术层面 2. 组织管理层面 3. 业务流程层面 三、数据孤岛带来的危害 1. 对企业决策的影响 2. 对业务运营效率的影响 3. 对数据治理和安全的影响 四、解决数据孤…

自定义Cereal XML输出容器节点

自定义Cereal XML输出容器节点 CEREAL_SERIALIZE_INTRUSIVE 在 1.优化Cereal宏 一行声明序列化函数 QString、QVector、QList、QMap序列化在2.在Cereal中支持Qt容器序列化 静态成员函数type_node检测在 3.利用SFINAE检测成员函数 🚀 告别value0:自定义Ce…

Spark 写入hive表解析

FileOutputCommitter中提交mapreduce.fileoutputcommitter.algorithm.version有v1和v2两个版本。 v1版本Spark写入文件的流程: 1.当task完成的时候,会将task的结果文件先写入到临时目录下面。 2.所有的task完成后,将所有的结果文件写入到结…

Linux云计算基础篇(5)

一、sudo是什么? 定义:sudo(SuperUserDO)是一个Linux/Unix系统命令,允许被授权的普通用户以另一个用户(通常是超级用户root)的身份执行命令。 核心目的: 1.最小权限原则:避免让用户长期拥有ro…