druid连接池 - 长时间阻塞问题排查

article/2025/9/15 18:39:30

前言

最近参与一个新项目,从老项目拷贝过来的代码,同样用的druid连接池 + PG。但是新项目却经常出现阻塞的情况,有时候甚至可以阻塞半个小时。一时间傻眼了。。

问题排查

问题背景

我们一共有6个开发同学,由于项目时间还是比较紧张的,所以大部分时间还是在开发,而不会发访问服务器。而当前阶段也还没有提测,没有其他同学的介入。而且每次第二天早上都会出现这种阻塞的情况。

请教DBA大佬

由于配置跟老项目一模一样,所以第一个反应是数据库出什么问题了?找DBA断断续续排查了好几天(太忙了,主要还是搞开发),最后发现数据库应该是正常的。但是有新发现

  • PG数据库的小版本不一样,新项目的要高一些
  • 新项目使用的JDK版本是java8,而老项目是java7

连接池

由于数据库排查结果是正常的,我只能找其他原因。于是我从tomcat的.out日志文件中重新找到被阻塞的线程的日志,找到Spring打印的DEBUG日志。发现确实是在获取数据库连接的时候被阻塞的。然后又梳理了一下应用的调用链路:

  • Spring -> ibatis -> druid -> PostgreSQL客户端 -> PostgreSQL服务器。

确定问题发生的地方只有两个地方了:要么是druid连接池,要么是PG客户端。

结合上一次两个项目的不同点,我顺着排查PG客户端,先升级PG客户端。发现问题依然存在。同时在PG的官方网站发现如果没有罕见情况,应当使用最新的java客户端

  • Current Version 42.3.1
    This is the current version of the driver. Unless you have unusual requirements (running old applications or JVMs), this is the driver you should be using. It supports PostgreSQL 8.2 or newer and requires Java 8 or newer. It contains support for SSL and the javax.sql package.

  • If you are using Java 8 or newer then you should use the JDBC 4.2 version.
    If you are using a Java version older than 6 then you will need to use a JDBC3 version of the driver, which will by necessity not be current, found in Other Versions.
    PostgreSQL JDBC 4.2 Driver, 42.3.1

至此,升级PG的java客户端无果。

Druid连接池

冷静下来,结合问题现象,每次第二天都会被阻塞,发现如下问题:

  1. 会不会是连接失效的原因?
  2. druid连接池不会移除失效连接?
  3. 是不是跟空闲连接有关,minIdle是多少?

顺着上面的问题,我找到了Druid连接池的连接销毁任务
在这里插入图片描述
druid连接池会保留最小的空闲连接数,并且销毁任务不会检查这些个连接是否有效,因此druid连接池会长期保留minIdle个连接。而在我们的场景下,这些连接肯定是都失效了的。

进一步看看,失效连接被出借的情况。上一次做druid连接池参数优化的时候,看了一下源码。在出借连接的时候还会做一次连接健康检查。
在这里插入图片描述
不管是testOnBorrow还是testWhileIdle都有可能做健康检查,不同的是testOnBorrow是一定会在出借连接时做检查,而testWhileIdle是有条件的。只有当连接空闲时间超过销毁任务的时间周期,才会被检查。默认是60s。

这也是网上大多推荐使用testWhileIdle的原因,因为连接空闲60s通常都还是可用的。但是这里有个坑就是,你不要装X去把这个timeBetweenEvictionRunsMillis时间调整更长,否则超时连接借出去了那就是你倒霉了。其实这个也算是druid的一个问题吧,因为同一个参数有好几个用途,牵一发而动全身,给耦合在一起了。

好了,我们应该是没有改这个配置,而在我们的场景下,一定会进入健康检查的,继续排查检查检查的代码。
在这里插入图片描述
发现这个健康检查是有设置超时时间的啊,奔溃啊。。然后发现个惊喜

protected volatile int validationQueryTimeout = -1;

翻译过来就是,按照不超时处理。这种情况下只能等待防火墙超时。。。

总论

于是大胆下结论:问题的元凶就是这个默认的健康检查超时时间,

  • 解决方案:只需要设置这个值为validationQueryTimeout = 2应该就可以了。可以在bean定义的时候使用property 标签赋值。注意哈,这个参数的时间单位是秒!
    这个超时时间也比较重要。例如,minIdle=10,超时时间为2s,那像我们这种业务场景意味着要20s后才能返回新的连接。因此要注意这两个参数的合理性

后记

其实我还没有用上面的方案试过,因为跟同事聊的时候,他说他们是改源码的方式修改超时时间的。。而那个时候,我就想改源码还是算了吧,项目路时间不允许啊。我使用的方案是,把minIdle设置为0,这样直接让销毁任务回收就行了。虽然也能解决问题,但确实不太好。下周找时间试试新方案。
设置超时时间的方案验证失败!原因待排查。
但直接把minIdle=0是可以解决问题的!


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

相关文章

Druid 连接池技术的使用

文章目录 官网链接连接性能消耗问题分析数据库连接池的作用市面常见连接池产品和对比国货之光druid连接池使用导入druid依赖硬编码方式(了解)软编码方式druid配置(了解) 官网链接 http://www.apache-druid.cn/GettingStarted/chapter-1.html 连接性能消…

druid连接池例子

先导入jia包 驱动jar包 druid的Jar包 写配置文件 定义配置文件(手动加载) 名称:自定义路径:自定义 封装工具类代码 package com.lingaolu.dataSource;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.Dat…

Druid连接池的使用

先了解什么是druid Druid是阿里开源的数据库连接池,作为后起之秀,性能比dbcp、c3p0更高,使用也越来越广泛。 当然Druid不仅仅是一个连接池,还有很多其他的功能。它还包含一个ProxyDriver,一系列内置的JDBC组件库&#…

SpringBoot整合Druid连接池

SpringBoot整合Druid连接池 前言第一种整合方式自定义的方式引入Druid依赖配置文件配置类实现监控功能开启SQL防火墙实现web应用访问Druid页面需登录 第二种整合方式引入SpringBoot的stater方式引入依赖分析自动配置具体配置示例重启服务测试 总结 前言 Druid是阿里巴巴开发的…

Druid连接池原理

一、数据库连接池初始化 (1)、 如果设置了maxWait或者构造函数参数传入的为true,则创建的ReentrantLock为公平锁,否者为非公平锁 (2)、 如果设置了initialSize>1,则会启动是创建initialSize个数数据库物理连接到线程池。 (3)、 如果没设置…

Druid之连接池

需要注意的是,我们下面提供的几种实现方式都是基于简单的原型,目的是带你了解连接池实现的一些基本原理。真实的数据库连接池技术需要考虑更多复杂的细节。 所以下面这些代码都是不能在生产上直接使用的。 实现的时候会用到java.sql.Connection&#x…

Druid连接池核心原理

一、什么是Druid连接池? Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。 竞品对比 从上表可以…

德鲁伊连接池(druid)

文章目录 一、连接池1、什么是连接池2、为什么要用连接池 二、德鲁伊连接池(druid)1.介绍2.代码实操 一、连接池 1、什么是连接池 简单来说就是一组连接组成的一个池子(集合),称为连接池。 连接池是创建和管理一个连接的缓冲池技术。 2、为什么要用连…

【Druid 连接池】 学习~快速 掌握连接池基本原理

文章目录 前言提出问题:一、Druid连接池简述 再次提出问题 :二、初始化连接池三、了解三个核心成员(三大线程)四、获取连接五、探活(连接池连接健康的检查机制) 前言 翻遍了各个大佬发的博客整理出来的学习…

Druid连接池的基本配置与使用

Druid简介 Druid是阿里巴巴的开源连接池组件,是世界上最好的连接池之一。Druid能对数据库连接进行有效管理和重用,最大化程序执行的效率。连接池负责创建和管理连接,程序只负责取用与归还。 以下是我画的示意图: 下面我来给大家…

MySQL快捷键注释

MySQL语句注释快捷键显示为CtrlOemQuestion,对应于我们键盘上的是Ctrl?

Mysql 增加表注释

关注微信公共号:小程在线 关注CSDN博客:程志伟的博客 方法一: mysql添加表注释 ALTER TABLE 表名 COMMENT 注释字段; 实例: alter table test comment 测试表; 方法二: 在创建表的时候直接增加表注释…

mysql语句中的注释方法_MySQL语句注释方式简介

MySQL支持三种注释方式: 1.从‘#字符从行尾。 2.从‘-- 序列到行尾。请注意‘-- (双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。 3.从/*序列到后面的*/序列。结束序列不一定在同一行中,因此该语法允许注释跨越多行…

MySQL注释:单行注释和多行注释,快进来理解

单行注释与多行注释 单行注释多行注释 单行注释 单行注释可以使用#注释符,#注释符后直接加注释内容 #注释内容单行注释可以使用- -注释符,- -注释符后需要加一个空格,注释才能生效。 -- 注释内容#和–的区别就是:#后面直接加注…

Mysql注释

Mysql注释 MySQL服务器支持3种注释风格: 从‘#’字符从行尾。 从‘-- ’序列到行尾。请注意‘-- ’(双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。该语法与标准SQL注释语法稍有不同。 从/*序…

mysql注释乱码问题_mysql注释是中文乱码怎么办

mysql注释是中文乱码的解决办法:首先用“show variables like”命令查看数据库与服务端的字符集设置;然后执行语句为“set collation_serverutf8_general_ci;”即可。 mysql表注释乱码 问题 执行语句: alter table TABLE_XXX comment ‘中文号’; 结果: …

wepy开发小程序eslint报错error 'getApp' is not defined no-undef

wepy开发小程序使用getApp().globalData保存全局数据很方便,但是会在控制台看到很多报错:“error getApp is not defined no-undef”,这是eslint报错。 解决办法:在.eslintrc.js文件中加入 globals: { getApp: true } 转载于:ht…

微信小程序 关于获取用户信息的一种方法 “this.setData与getApp().globalData.userInfo“

获取用户信息&#xff1a;this.setData和getApp().globalData.userInfo; 最开始的WXML文件中&#xff0c;我们写下页面结构代码如下&#xff1a; <image class"userinfo-avatar" src"{{userInfo.avatarUrl}}" mode"cover"></image>…

JS交互逻辑——获取页面数据{{}}和全局数据const app = getApp()

JS交互逻辑 在小程序里边&#xff0c;我们就通过编写 JS 脚本文件来处理用户的操作 app.js中最外层需要App({}) &#xff0c;该函数是微信平台提供的api App({// 全局数据&#xff0c;可以在所有的子页面中使用mydata: {n: 100} }) // 页面获取全局数据的方式,app表示小程序的…

微信小程序getApp().globalData.user无法获取值

一、debug过程 在进行微信小程序的开发过程中&#xff0c;我利用如下代码获取全局变量中的username的值&#xff0c;但其结果缺如图中所示的只向数据库中存入了对应的类型即object Object。 username: getApp().globalData.user.username, 数据库结果 其中&#xff0c;全局变量…