Hikari连接池——java.lang.Exception: Apparent connection leak detected

article/2025/9/26 3:00:46

Hikari连接池——java.lang.Exception: Apparent connection leak detected

  • 问题分析
  • 总结

问题分析

首先,先看报错:

java.lang.Exception: Apparent connection leak detectedat com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128) ~[HikariCP-3.4.5.jar:?]at com.skyline.MyTest.getConnection(MyTest.java:36)at java.lang.Thread.run(Thread.java:748) [?:1.8.0_261]

Apparent connection leak detected,网上很多解释都说是连接泄露,但是这个报错就等于连接泄漏了吗?先说答案:并不是!!!
首先,这个报错是从ProxyLeakTask中抛出来的,源码不多,先贴出来

class ProxyLeakTask implements Runnable
{private static final Logger LOGGER = LoggerFactory.getLogger(ProxyLeakTask.class);static final ProxyLeakTask NO_LEAK;//调度器private ScheduledFuture<?> scheduledFuture;private String connectionName;//异常对象private Exception exception;//线程名private String threadName; //是否泄露private boolean isLeaked;static{//创建一个不检测连接泄漏的taskNO_LEAK = new ProxyLeakTask() {@Overridevoid schedule(ScheduledExecutorService executorService, long leakDetectionThreshold) {}@Overridepublic void run() {}@Overridepublic void cancel() {}};}//构造器,需要传入连接池中的连接对象ProxyLeakTask(final PoolEntry poolEntry){//※重点来了,这时创建一个异常对象,当ProxyLeakTask被new出来的时候,就是连接被业务代码申请的时候this.exception = new Exception("Apparent connection leak detected");this.threadName = Thread.currentThread().getName();this.connectionName = poolEntry.connection.toString();}private ProxyLeakTask(){}//※很重要,开始调度到倒计时开始void schedule(ScheduledExecutorService executorService, long leakDetectionThreshold){//拿到这个返回值是为了将来可以cancel这个调度scheduledFuture = executorService.schedule(this, leakDetectionThreshold, TimeUnit.MILLISECONDS);}/** {@inheritDoc} */@Overridepublic void run(){//当代码执行到这里时,说明上面的调度没有被cancel,//那么Hikari就认为之前申请的连接可能已经泄露了,//这个run方法是由executorService回调的isLeaked = true;final StackTraceElement[] stackTrace = exception.getStackTrace(); final StackTraceElement[] trace = new StackTraceElement[stackTrace.length - 5];System.arraycopy(stackTrace, 5, trace, 0, trace.length);exception.setStackTrace(trace);LOGGER.warn("Connection leak detection triggered for {} on thread {}, stack trace follows", connectionName, threadName, exception);}//取消调度,这个方法会在连接被释放时回调void cancel(){//先把这个调度任务取消scheduledFuture.cancel(false);if (isLeaked) {//很遗憾,如果之前调度任务已经走过了,那么就再打个日志说明一下//之前那个被认为已经泄露了的连接会到池子里了LOGGER.info("Previously reported leaked connection {} on thread {} was returned to the pool (unleaked)", connectionName, threadName);}}
}

接下来我们看下ProxyLeakTask是什么时候被创建的,首先,我们来到这个方法:com.zaxxer.hikari.pool.HikariPool#getConnection(long)这个是从Hikari中获取连接的方法,大家都知道,但凡你要操作数据库,必然先取连接。我们重点关注一下这个方法 poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);
在这里插入图片描述
一层一层的看,我们先看这个leakTaskFactory.schedule方法:

ProxyLeakTask schedule(final PoolEntry poolEntry)
{//先判断leakDetectionThreshold是不是等于0,//如果等于0,返回最一开始那个不检查连接泄露的Task,//如果不等于0,就通过scheduleNewTask创建一下return (leakDetectionThreshold == 0) ? ProxyLeakTask.NO_LEAK : scheduleNewTask(poolEntry);}

重头戏scheduleNewTask来了

private ProxyLeakTask scheduleNewTask(PoolEntry poolEntry) {//创建一个taskProxyLeakTask task = new ProxyLeakTask(poolEntry);//开始调度,※注意,这里就开始倒计时了!!!!task.schedule(executorService, leakDetectionThreshold);return task;
}

那么poolEntry.createProxyConnection返回的是个什么对象呢?答案是com.zaxxer.hikari.pool.ProxyConnection这里肯定是代理了。我们重点关注一下连接释放的方法吧:
在这里插入图片描述
看到没有,当连接被释放时,会回调leakTask的cancel方法。

总结

  1. leakDetectionThreshold如果等于0,那么Hikari就不会做连接泄露的检查
  2. leakDetectionThreshold的时间=从获取调用getConnection()开始到调用connection.close()的时间,注意,如果从数据库中获取真正的连接的耗时也是计算在内的!
  3. Apparent connection leak detected并不等于连接泄露,我理解只能是猜测可能出现了连接泄露,如果日志中可以找到成对的Previously reported leaked connection {} on thread {} was returned to the pool (unleaked)那么可以确定的是,连接并没有泄露,只是连接的使用时长>leakDetectionThreshold了,虽然不是连接泄露,但是可能是执行慢的SQL,也是需要进一步跟踪排查的
  4. 这个连接泄露的检查机制真的很厉害,从来没想过调度任务可以这么玩,确实有意思,打开了新世界的大门。

引申一下,leakDetectionThreshold的配置项在spring.datasource.hikari.leak-detection-threshold单位是毫秒


http://chatgpt.dhexx.cn/article/iGp48amT.shtml

相关文章

ERROR com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.

错误截图&#xff08;截取一部分&#xff09;&#xff1a; 解决方法&#xff1a;去网上查看发现需要加useSSLfalse&#xff0c;在后面拼接上。这个的意思是禁用SSL。 上代码&#xff1a; spring.datasource.urljdbc:mysql://localhost:3306/springdd?serverTimezoneAsia/Sha…

mysql hikari连接池异常处理(com.zaxxer.hikari.pool.ProxyConnection)

异常信息如下&#xff1a;com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 603,312 milliseconds ago. ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.CommunicationsException: T…

Hikari连接泄露分析:Apparent connection leak detected

Hikari连接池故障 前两天生产环境上触发了触发了CPU飙升的预警短信&#xff0c;查看日志发现出现如下数据库连接池的报错&#xff0c;通过网上查阅资料发现HikariCP连接泄露时就会抛出此异常。 故障分析 Hikari的相关配置 leak-detection-threshold&#xff1a;用来设置连接…

springboot实现多数据源配置(Druid/Hikari)

使用springbootmybatis-plus&#xff08;Druid/Hikari&#xff09;实现多数据源配置 操作步骤&#xff1a; 引入相应的maven坐标编写mybatis配置&#xff0c;集成mybatis或mybatis-plus&#xff08;如果已集成可跳过&#xff09;编写数据源配置类编写注解&#xff0c;并通过a…

HikariDataSource

DataSourceConfiguration 配置类&#xff0c;springBoot默认采用HikariDataSource /*** Hikari DataSource configuration.*/Configuration(proxyBeanMethods false)ConditionalOnClass(HikariDataSource.class)ConditionalOnMissingBean(DataSource.class)ConditionalOnPro…

Hikari

HikariCP 1 简介 数据库连接池就是在程序初始化的时候&#xff0c;预先创建一定数量的数据库连接对象&#xff0c;当后续需要数据库连接的时候&#xff0c;如果此时有连接未被使用&#xff0c;那么他就可以直接使用已经创建好的连接&#xff0c;不需要再重新创建新的连接&…

关于Hikari连接池的源码理解与配置使用

关于Hikari连接池的源码理解与配置使用 1. 连接池初始化 1.1 初始化连接池 对于应用者来说&#xff0c;我们构造一个线程池就是构造一个HikariDataSource。 重点看一下获取连接以及相关连接管理的流程。 public Connection getConnection() throws SQLException {if (this…

Hikari 讲解

前言 现在已经有很多公司在使用HikariCP了&#xff0c;HikariCP还成为了SpringBoot默认的连接池&#xff0c;伴随着SpringBoot和微服务&#xff0c;HikariCP 必将迎来广泛的普及。 下面带大家从源码角度分析一下HikariCP为什么能够被Spring Boot 青睐&#xff0c;文章目录如下…

SpringBoot系列十八:整合Hikari

Hikari是一款非常强大&#xff0c;高效&#xff0c;并且号称“史上最快连接池”。并且在springboot2.0之后&#xff0c;采用的默认数据库连接池就是Hikari。不需要引入依赖&#xff0c;已经在SpringBoot中包含了。  GitHub地址&#xff1a;https://github.com/brettwooldridge…

Android开发之RelativeLayout

文章目录 常见属性根据父容器定位根据兄弟容器定位 实例根据父容器定位根据兄弟组件定位 通用属性设置组件与父容器的边距设置父容器与组件的边距 常见属性 根据父容器定位 layout_alignParentStart 左对齐 layout_alignParentEnd 右对齐 layout_alignParentTop 顶部对齐 lay…

Android RelativeLayout布局

1. RelativeLayout类 相对布局&#xff08;RelativeLayout&#xff09;将子视图以相对位置显示。默认显示在父视图的左上角。 layout_alignParentTop&#xff0c;父视图的上边layout_alignParentBottom&#xff0c;父视图的下边layout_alignParentLeft&#xff0c;父视图的左…

android 继承relativelayout,Android开发中RelativeLayout相对布局

Android开发中RelativeLayout相对布局 RelativeLayout布局是Android界面布局中应用最广也最强大的一种布局&#xff0c;其不只十分灵活&#xff0c;能够解决开发中各类界面布局需求&#xff0c;同时也很方便了解决了多屏幕尺寸的适配问题。在iOS开发中&#xff0c;Autolayout技…

RelativeLayout实现居中偏下x距离引发的小问题

UE想实现一个简单的效果&#xff0c;某个控件在屏幕水平线下方50dp。由于受限于项目历史布局&#xff08;RelativeLayout&#xff09;和一套动态化设置控件位置的方案&#xff0c;竟然遇到了一点问题。&#xff08;在这里还是喊一声&#xff1a;ConstraintLayout最香&#xff0…

RelativeLayout布局

RelativeLayout布局是相对布局&#xff0c;如果RelativeLayout中再包含两个RelativeLayout&#xff0c;不会像LinearLayout一样&#xff0c;宽高一样的话会重叠在一起 将红色布局放到右上角 常见属性 根据父容器定位 layout_alignParentLeft 左对齐 layout_alignParentRig…

RelativeLayout圆角处理

RelativeLayout圆角处理以后&#xff0c;可以变相对子view进行圆角处理&#xff0c;如ImageView&#xff0c;VideoView等 RoundRelativeLayout具体实现 比较简单&#xff0c;只需要在初始化时设置一下layout的ViewOutlineProvider&#xff0c;方便起见&#xff0c;这里写死rad…

RelativeLayout(相对布局)的基本使用

RelativeLayout又称作相对布局&#xff0c;也是一种非常常用的布局。和LinearLayout的排列规则不同&#xff0c;RelativeLayout显得更加随意一些&#xff0c;它可以通过相对定位的方式让控件出现在布局的任何位置。也正因为如此&#xff0c;RelativeLayout中的属性非常多&#…

RelativeLayout相对布局详解

RelativeLayout相对布局在Android UI开发中也应用比较多&#xff0c;虽然它不及LinearLayout使用方便&#xff0c;但某些场景中使用RelativeLayout也是一种很不错的选择。在官网上介绍RelativeLayout是一个视图组&#xff0c;在相对位置显示子视图。RelativeLayout是用于设计用…

Android相对布局(RelativeLayout)

Android相对布局(RelativeLayout) 备注&#xff1a;这里的视图和元素是等同的概念。 RelativeLayout是一个允许子视图相对于其他兄弟视图或是父视图显示的视图组(通过ID指定)。每个视图的位置能够指定它相对于兄弟(比如在其他视图的左边或是下边)或是父视图(这里是指相对布局容…

【Android】相对布局(RelativeLayout)最全解析

【Android】相对布局&#xff08;RelativeLayout&#xff09;最全解析 一、相对布局&#xff08;RelativeLayout&#xff09;概述二、根据父容器定位三、根据兄弟控件定位 一、相对布局&#xff08;RelativeLayout&#xff09;概述 相对布局&#xff08;RelativeLayout&#x…

Flutter ListView详解

ListView详解 ListView常用构造ListViewListView 默认构建效果 ListView ListTileListTile 属性ListTile 使用效果 ListView builderbuilder属性详细介绍分析几个比较难理解的属性效果builder模式来设置分割线 ListView separatedseparatorBuilderseparated设置分割线效果 List…