Spring Boot 应用 “Connection is closed” 及 MySQL 空闲超时断开连接解决方案

news2024/12/14 16:21:37

在使用 Spring Boot + MySQL + HikariCP 的组合时,可能会在生产或测试环境中遭遇类似如下异常信息:

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT ...]; 
SQL state [null]; error code [0]; Connection is closed; 
nested exception is java.sql.SQLException: Connection is closed

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT ...];
SQL state [HY000]; error code [4031]; 
The client was disconnected by the server because of inactivity. 
See wait_timeout and interactive_timeout for configuring this behavior.
...
Caused by: java.sql.SQLException: The client was disconnected by the server because of inactivity.

对于初次遇到此类问题的开发者来说,这往往令人困惑:连接池不是已经帮我们管理连接了吗?为什么还会出现连接被关闭的异常?本文将从问题现象出发,深入分析原因,并给出一些行之有效的解决方案,帮助你解决该问题。

问题现象

在一个正常运行的 Spring Boot 应用中,有时在调用数据库查询接口时会突然报出上述错误信息。其典型特征如下:

  1. Connection is closed:表示在执行 SQL 时发现当前使用的数据库连接已经被关闭,无法继续使用。
  2. The client was disconnected by the server because of inactivity:明确指出 MySQL 服务端在无操作的情况下,主动断开了该连接。

从报错信息可知,客户端(即应用侧)认为自己的连接还在池中可用,但当真正执行 SQL 时却发现服务器端已经将连接回收或断开。这通常意味着连接池中的空闲连接在长时间未使用后失效,当再次被应用取用时引发异常。

原因分析

问题的源头在于 数据库空闲连接的超时与连接池管理机制的交互

  1. MySQL 服务端空闲超时机制:MySQL 会针对长时间处于空闲状态的连接进行自动回收。决定这一过程的关键参数是 wait_timeoutinteractive_timeout。如果连接在一段时间(默认通常是8小时)内未发生任何交互,MySQL 就会主动关闭该连接。
  2. 连接池未定期验证连接可用性:虽然使用了 HikariCP 这样优秀的连接池工具,但如果连接池在将连接归还到池中后,没有执行定期的心跳检测或验证查询,那么当这些连接在池中 “沉睡” 超过 MySQL 的超时时间后,它们会在 MySQL 端被关闭,但连接池本身仍认为这条连接是有效的空闲连接。
  3. 连接重用导致的意外报错:当应用再次从连接池取出这条被 MySQL 已断开的连接试图执行查询时,就会触发上述异常。

解决方案

调整 MySQL 服务端的超时参数(可选)

根据实际业务场景,如果长时间的空闲连接是业务特性(例如夜间业务量很低,白天又有高峰请求),可以适当增大 MySQL 的 wait_timeoutinteractive_timeout 来减少连接被过早回收的概率。

SET GLOBAL wait_timeout = 28800;        -- 设置空闲超时为8小时
SET GLOBAL interactive_timeout = 28800; -- 同上

不过,这只是缓解手段,并非最终方案。过度延长空闲时间并不总是明智,因为这会占用数据库资源。

在 HikariCP 层面实施连接保活策略(推荐)

HikariCP 已经为我们提供了对连接健康检查的良好支持。通过适当地配置,它可以定期验证连接是否仍然有效,并在其被回收前主动进行一个类似 “心跳” 的查询。

关键配置项可包括:

  • connection-test-query:用于验证连接有效性的查询,一般为简单的 SELECT 1SELECT 1 FROM DUAL(根据数据库类型决定)。
  • validation-timeout:验证连接可用性的超时时间。
  • keepalive-time(HikariCP 3.4.1+ 提供):为空闲连接添加心跳检测,即使在没有请求使用时,HikariCP 也会周期性地发送校验查询,以防止连接因空闲被断开。

示例配置(application.yml):

spring:
  datasource:
    hikari:
      # 测试连接的查询
      connection-test-query: SELECT 1
      # 每5分钟对空闲连接进行一次心跳测试
      keepalive-time: 300000
      # 验证连接有效性的超时时间为5秒
      validation-timeout: 5000
      # 连接池中的最大连接数(建议 < MySQL max.connections)
      maximum-pool-size: 100
      # 最小空闲连接数
      minimum-idle: 10
      # 连接在池中存活30分钟后重建,防止意外长连接问题
      max-lifetime: 1800000
      # 客户端从池中获取连接的最大等待时间(以毫秒为单位), 超过此时间将抛出异常 30s
      connection-timeout: 30000
      # 启用自动提交模式
      auto-commit: true
      # 连接在池中允许空闲的最长时间(毫秒为单位) 10min
      idle-timeout: 600000
      # 连接池的名称
      pool-name: DatebookHikariCP

通过增加 keepalive-timeconnection-test-query 等参数,当连接空闲达到一定时长时,HikariCP 会自动执行一次 “心跳” 查询,确保该连接始终处于活跃状态。如果该连接已被 MySQL 回收,心跳检测会及时发现并主动从池中移除该连接并新建连接,以确保在真正使用时不出故障。

connection-test-query 说明:

HikariCP 在较新版本中会在需要时自动使用 Connection.isValid() 来检测连接,无需手动指定 connection-test-query。如果你的数据库版本和 JDBC 驱动都支持 isValid() 方法,可以考虑去掉 connection-test-query,让 HikariCP 的内置机制发挥作用,从而减少不必要的测试查询开销。

keepalive-time 说明:

上面将 keepalive-time 设置为5分钟(300000 ms)。这会在连接闲置5分钟后对其进行一次心跳检测,以确保其保持可用。如果你的数据库超时时间较长或者系统较为稳定,你也可以适度延长该时间间隔,减少心跳查询的开销。不过,这需要在业务闲置周期和数据库超时策略之间找到平衡点。

maximum-pool-size 与 minimum-idle 说明:

maximum-pool-size: 100minimum-idle: 10 已算是较为通用的配置。但实际最优值要依据你的并发量、数据库负载、服务器资源等多方面因素来定。如果你的系统在高峰期请求量很大,且需要保持较多的“预热”连接,可以适当提高 minimum-idle,这样在高峰来临时连接池能更快提供足够连接。反之,如果系统较少需要瞬时高并发,你可以适当降低 minimum-idle 减少资源占用。

连接寿命与超时时间说明:

max-lifetime: 1800000 (30分钟)和 idle-timeout: 600000 (10分钟) 通常是合理的默认值。max-lifetime 可以确保连接不会在池中永久存在(避免连接状态异常积累),idle-timeout 可以减少长期闲置连接占用资源。根据具体情况可考虑微调。例如,如果数据库 wait_timeout 为8小时,而你每隔5分钟有keepalive,会在连接超时前刷新连接,不见得需要30分钟就重建连接。但此设置能在更长周期内避免意外的连接状态问题。

connection-timeout 说明:

connection-timeout: 30000 ms 表示当请求获取连接超过30秒未成功就抛出异常。这对多数场景足够宽裕,但如果你的系统对请求延迟敏感,希望快速降级,也可稍微缩短该时间。

auto-commit: true 说明:

通常大多数查询和更新操作在 Spring 事务管理下是可以自动提交的。如果你的代码使用事务注解(@Transactional)来控制提交/回滚,这个设置一般没有问题。但请确保应用程序层面事务管理逻辑清晰。

业务侧定期 “热身”(非必要)

在大多数情况下,通过 HikariCP 的保活机制已经足够。如果业务场景特殊,可以在非高峰期通过定期任务(例如定时执行一次简单查询)来保持连接活性。但这通常是冗余且不太优雅的做法。

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

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

相关文章

【竞技宝】LOL:JDG官宣yagao离队

北京时间2024年12月13日,在英雄联盟S14全球总决赛结束之后,各大赛区都已经进入了休赛期,目前休赛期也快进入尾声,LPL大部分队伍都开始陆续官宣转会期的动向,其中JDG就在近期正式官宣中单选手yagao离队,而后者大概率将直接选择退役。 近日,JDG战队在官方微博上连续发布阵容变动消…

2024美赛数学建模C题:网球比赛中的动量,用马尔可夫链求解!详细分析

文末获取历年美赛数学建模论文&#xff0c;交流思路模型 接下来讲解马尔可夫链在2024年C题中的运用 1. 马尔科夫链的基本原理 马尔科夫链是描述随机过程的一种数学模型&#xff0c;其核心特征是无记忆性。 简单来说&#xff0c;系统在某一时刻的状态只取决于当前状态&#x…

图形学笔记 - 5. 光线追踪 - RayTracing

Whitted-Style Ray tracing 为什么要光线追踪 光栅化不能很好地处理全局效果 软阴影尤其是当光线反射不止一次的时候 栅格化速度很快&#xff0c;但质量相对较低 光线追踪是准确的&#xff0c;但速度很慢 光栅化&#xff1a;实时&#xff0c;光线追踪&#xff1a;离线~10K …

Nginx之配置防盗链(Configuring Anti-hotlinking in Nginx)

运维小白入门——Nginx配置防盗 什么是防盗链&#xff1a; 防盗链技术主要用于防止未经授权的第三方或域名访问网站的静态资源。例如&#xff0c;一个网站可能拥有独特的图片素材&#xff0c;为了防止其他网站通过直接链接图片URL的方式访问这些图片&#xff0c;网站管理员会采…

51c大模型~合集89

我自己的原文哦~ https://blog.51cto.com/whaosoft/12815167 #OpenAI很会营销 而号称超强AI营销的灵感岛实测成效如何&#xff1f; OpenAI 是懂营销的&#xff0c;连续 12 天发布&#xff0c;每天一个新花样&#xff0c;如今刚过一半&#xff0c;热度依旧不减。 毫无疑问&…

深度学习的unfold操作

unfold&#xff08;展开&#xff09;是深度学习框架中常见的数据操作。与我们熟悉的卷积类似&#xff0c;unfold也是使用一个特定大小的窗口和步长自左至右、自上至下滑动&#xff0c;不同的是&#xff0c;卷积是滑动后与核求乘积&#xff08;所以取名为卷积&#xff09;&#…

Jetpack Compose赋能:以速破局,高效打造非凡应用

Android Compose 是谷歌推出的一种现代化 UI 框架&#xff0c;基于 Kotlin 编程语言&#xff0c;旨在简化和加速 Android 应用开发。它以声明式编程为核心&#xff0c;与传统的 View 系统相比&#xff0c;Compose 提供了更直观、更简洁的开发体验。以下是对 Android Compose 的…

Dual-Write Problem 双写问题(微服务)

原文链接https://www.confluent.io/blog/dual-write-problem/ 双写问题发生于当两个外部系统必须以原子的方式更新时。 问题 说有人到银行存了一笔钱&#xff0c;触发 DepositFunds 命令&#xff0c;DepositFunds 命令被发送到Account microservice。 Account microservice需…

桥接模式的理解和实践

桥接模式&#xff08;Bridge Pattern&#xff09;&#xff0c;又称桥梁模式&#xff0c;是一种结构型设计模式。它的核心思想是将抽象部分与实现部分分离&#xff0c;使它们可以独立地进行变化&#xff0c;从而提高系统的灵活性和可扩展性。本文将详细介绍桥接模式的概念、原理…

kubeadm安装K8s集群之高可用组件keepalived+nginx及kubeadm部署

系列文章目录 1.kubeadm安装K8s集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s集群之master节点加入 4.kubeadm安装K8s集群之worker1节点加入 kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 1.安装kubeadm…

Avalonia实战实例三:实现可输入框的ComboBox控件

文章目录 一、Avalonia中的ComboBox控件二、更改Template&#xff0c;并添加水印 接着上篇关闭按钮实现登录界面 实现一个可输入&#xff0c;可下拉的用户名输入框 一、Avalonia中的ComboBox控件 Avalonia中Fluent主题里ComboBox实现&#xff1a; <ControlTheme x:Key&q…

TMS320C55x DSP芯片结构和CPU外围电路

第2章 DSP芯片结构和CPU外围电路 文章目录 第2章 DSP芯片结构和CPU外围电路TMS320C55x处理器的特点TMS320c55x CPU单元指令缓冲(Instruction Buffer Unit) I单元程序流程(Program Flow Unit) P单元地址数据(Address-data Flow Unit) A单元数据计算(Data Computation Unit) D单元…

Oracle 与 达梦 数据库 对比

当尝试安装了达梦数据库后&#xff0c;发现达梦真的和Oracle数据库太像了&#xff0c;甚至很多语法都相同。 比如&#xff1a;Oracle登录数据库采用sqlplus&#xff0c;达梦采用disql。 比如查看数据视图&#xff1a;达梦和Oracle都有 v$instance、v$database、dba_users等&a…

数据结构之五:排序

void*类型的实现&#xff1a;排序&#xff08;void*类型&#xff09;-CSDN博客 一、插入排序 1、直接插入排序 思想&#xff1a;把待排序的数据逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。 单趟&#x…

JavaWeb:JavaScript

学习 资源1 学习资源 2 黑马javaweb 1、引入方式 内部脚本&#xff1a; <script>内容</script> 外部脚本&#xff1a; <script src"js/test.js"></script> 2、基础语法 注释&#xff1a;// /* */ 结尾分号可有可无 大括号表示代码块 …

MySQL其五,索引详解,逻辑架构,SQL优化等概念

目录 一、索引 1、索引的概念 2、索引的优缺点 3、添加索引的原则 4、索引的分类 5、索引如何使用 6、存储过程讲解 7、测试索引的效率 7、索引的数据结构 8、覆盖索引&#xff08;SQL优化的点&#xff09; 9、最佳左前缀法则&#xff08;SQL优化的点&#xff09; 二…

考研数学【线性代数基础box(数二)】

本文是对数学二线性代数基础进行总结&#xff0c;一些及极其简单的被省略了&#xff0c;代数的概念稀碎&#xff0c;不如高数关联性高&#xff0c;所以本文仅供参考&#xff0c;做题请从中筛选&#xff01; 本文为初稿&#xff0c;后面会根据刷题和自己的理解继续更新 第一章…

全面解析租赁小程序的功能与优势

内容概要 租赁小程序正在逐渐改变人与物之间的互动方式。通过这些小程序&#xff0c;用户不仅可以轻松找到所需的租赁商品&#xff0c;还能够享受无缝的操作体验。为了给大家一个清晰的了解&#xff0c;下面我们将重点介绍几个核心功能。 建议&#xff1a;在选择租赁小程序时&…

Linux DNS 协议概述

1. DNS 概述 互联网中&#xff0c;一台计算机与其他计算机通信时&#xff0c;通过 IP 地址唯一的标志自己。此时的 IP 地址就类似于我们日常生活中的电话号码。但是&#xff0c;这种纯数字的标识是比较难记忆的&#xff0c;而且数量也比较庞大。例如&#xff0c;每个 IPv4 地址…

Java使用ORM Bee自动生成Javabean.

Java使用ORM Bee自动生成Javabean. 配置数据库连接,添加了pom.xml依赖后,就可以写Java代码,自动生成Javabean了. 可参考:https://gitee.com/automvc/bee https://github.com/automvc/bee 还可以生成字段文件, 这样可以避免硬编码引用字段,速度也比反射快. package org.tea…