记录一次解决数据库连接池连接泄露BUG
1 BUG现象
系统并发请求,系统停滞无法使用,所有接口都是无法与后端进行交互的状态,系统并没有宕机
2 BUG的业务流程
- 插入分数方法 涉及插入表ABCD 加了声明式事务
- 查询分数方法 涉及表ABCD
controller() {
@Transactional
insertVo();
selectById();
}
3 排查原因
因为代码不是我写的,一开始我就是怀疑是死锁导致的BUG,然后我用Jconsole,去检测一下死锁,并没有发现死锁,接下来我去Mysql看有没有死锁,结果也没有发现,然后我就懵了,jvm没有锁,mysql也没有锁且没有SQL在执行,为什么请求就会全注阻塞?
然后我去开始去看这个代码了,我发现他在控制层调用了两个业务层,通常我们只在控制层去做校验去调用一个service啊,然后我就继续看,insertVo插入了很多查询了很多,耗时3秒钟左右,selectById查询了一条SQL,这两个明面上的代码并没有什么加锁或什么飞天操作,想了半天搞不懂为什么。
然后我开始用排除法,把这些代码一一注释调试一下。我把insertVo注释掉,这个毋庸置疑,那只有一个简单的操作了,就查一表返回,这个绝对是没问题的,然后我把selectById注释掉,居然就好了?,selectById只有一条查询SQL啊也没有加锁,这个能解决但是肯定也不是这个原因。
然后我用druid监控到可使用连接数一直在占用,没有释放,我就去查druid配置,发现配置了
initial-size: 20 #初始大小
min-idle: 20 #最小空闲
max-active: 40 #最大链接
max-wait: 10000 #配置获取连接等待超时的时间
这个配置也没有毛病啊,没办法了我只能去看线程的具体信息了,查出来所有的线程池连接线程都是这样的
"pool-6-thread-10" #244 prio=5 os_prio=31 tid=0x00007fe94235f000 nid=0x22803 waiting on condition [0x00000003150ce000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c109e090> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:2315)
at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1781)
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1494)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5058)
at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:704)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5054)
at com.alibaba.druid.filter.FilterAdapter.dataSource_getConnection(FilterAdapter.java:2759)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5054)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1469)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1459)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:83)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection(NonContextualJdbcConnectionAccess.java:38)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:104)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:134)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:250)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:258)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:246)
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:83)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:184)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:402)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:376)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:572)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:360)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.treach.platform.modules.service.impl.SysLogService$$EnhancerBySpringCGLIB$$36a85251.insert(<generated>)
at com.treach.platform.log.factory.LogTaskFactory$2.run(LogTaskFactory.java:56)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Locked ownable synchronizers:
- <0x00000007741f0d68> (a java.util.concurrent.ThreadPoolExecutor$Worker)
是的,连接池连接一直被占用锁住了,为什么会被锁住呢?,也设置了连接等待超时时间啊,然后我怀疑是配置没有生效,写了个代码看看
public static void main(String[] args) throws SQLException {
ConfigurableApplicationContext run = SpringApplication.run(NdCyApplication.class, args);
DruidDataSource bean = run.getBean(DruidDataSource.class);
int maxActive = bean.getMaxActive();
long maxWait = bean.getMaxWait();
log.info("数据库线程池与数据库最大链接数" + String.valueOf(maxActive));
log.info("数据库线程池等待链接数超时时间"+String.valueOf(maxWait));
}
结果:
数据库线程池与数据库最大链接数8
数据库线程池等待链接数超时时间-1
这个和配置的不一样啊,真的没有生效,然后我又去查为什么没有生效,原来配置类里面有个DataSoure
@Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource dataSource(){
DruidDataSource datasource = new DruidDataSource();
List<Filter> filters = new ArrayList<>();
filters.add(wallFilter);
filters.add(new StatFilter());
datasource.setProxyFilters(filters);
return datasource;
}
我们applcation.yaml的配置被覆盖了,druid默认等待链接数超时时间-1,难怪长时间占用连接没有超时。
4 解决
把等待连接超时时间等设置上
@Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource dataSource(){
DruidDataSource datasource = new DruidDataSource();
datasource.setInitialSize(20);
datasource.setMaxActive(80);
datasource.setMaxWait(5000);
List<Filter> filters = new ArrayList<>();
filters.add(wallFilter);
filters.add(new StatFilter());
datasource.setProxyFilters(filters);
return datasource;
}
成功
5 不懂的点
为什么会出现不回收线程的情况 按理来说现在没有SQL在执行,连接数不是会被回收吗 回到线程池 等待的线程就有连接了 就能不卡死了 为什么呢?
记录一次解决数据库连接池连接泄露BUG的更多相关文章
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题 最近有个问题非常讨厌,我们的工程中使用自己的连接池连接mysql数据库,可mysql数据库每隔8小时就会自动断开所有链接, ...
- Java使用数据库连接池连接Oracle数据库
第一步:导入tomcat\lib 下的一个tomcat-dbcp.jar包第二步:在web\META-INF下新建一个context.xml文件,文件内容如下: <?xml version=&q ...
- C3P0数据库连接池的相关bug解决
数据库连接池的几个常见bug: 1.警告: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@76c7022e -- ...
- EF Core 小坑:DbContextPool 会引起数据库连接池连接耗尽
DbContextPool 是 ASP.NET Core 2.1 引入的新特性,可以节省创建 DbContext 实例的开销,但没有想到其中藏着一个小坑. 最近有一个 ASP.NET Core 项目持 ...
- Myeclipse WEB工程JSP使用JNDI 数据库连接池连接Mysql数据库
在网上查了很多,最后实现了.下面写一下过程: 首先,在WEBROOT/META-INF下建一个文件context.xml,内容为: <?xml version="1.0" e ...
- springboot druid 数据库连接池连接失败后一直重连
在使用个人阿里云测试机,在查询实时输出日志时,看到数据库连接失败后,服务器一直在重连服务器.开始以为是遭受重复攻击,后面把服务重启后,就没有出现一直重连的情况.看以下输出日志: 2022-02-09 ...
- spring c3p0数据库连接池连接配置
c3p0连接池配置 xml文件内容如下: C3P0 通过这些属性,可以对数据源进行各种有效的控制 lc_biz_datasource_c3p0.properties 配置: lc_biz_dataso ...
- 使用c#数据库连接池
摘自: http://www.wxphp.com/wxd_0fetn2bw2548fsc2ak8h_1.html 导读:使用C#数据库连接池,连接到数据库服务器通常由几个需要软长时间的步骤组成,必须与 ...
- c#与oracle数据库连接池
c#与oracle数据库连接池 在做一个项目,中间要使用webservice和oracle数据库.我在服务端做了用户身份认证,也就是使用session传递用户的登陆信息.在测试时,当用户少的时候,没有 ...
- 01_数据库连接池,数据源,ResultSetMetaData,jdbc优化
一.数据库连接池 1. 什么是连接池 传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接. 这样的方式会导致用户每 ...
随机推荐
- 2022-10-23:给你一个整数数组 nums 。如果 nums 的一个子集中, 所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集 。 比方说,如果 nums =
2022-10-23:给你一个整数数组 nums .如果 nums 的一个子集中, 所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集 . 比方说,如果 nums = ...
- 2021-01-19:mysql中,一张表里有3亿数据,未分表,其中一个字段是企业类型,企业类型是一般企业和个体户,个体户的数据量差不多占50%,根据条件把个体户的行都删掉。请问如何操作?
2021-01-19:mysql中,一张表里有3亿数据,未分表,其中一个字段是企业类型,企业类型是一般企业和个体户,个体户的数据量差不多占50%,根据条件把个体户的行都删掉.请问如何操作?福哥答案20 ...
- 2021-02-21:手写代码:高性能路由,也就是一个字符串和多个匹配串进行模糊匹配。一个数组arr里是["*a*","moonfdd"],字符串"moonfdd"能匹配到,理由是arr里有。字符串"xayy"也能匹配到,理由是arr里的"*a*",第1个星对应"x",第2个星对应"yy"。
2021-02-21:手写代码:高性能路由,也就是一个字符串和多个匹配串进行模糊匹配.一个数组arr里是["a","moonfdd"],字符串"moo ...
- 2021-02-17:规定1和A对应、2和B对应、3和C对应...26和Z对应,那么一个数字字符串比如"111”就可以转化为:"AAA"、"KA"和"AK"。给定一个只有数字字符组成的字符串str,请问有多少种转化结果?
2021-02-17:规定1和A对应.2和B对应.3和C对应...26和Z对应,那么一个数字字符串比如"111"就可以转化为:"AAA"."KA&qu ...
- 图数据库 NebulaGraph 的内存管理实践之 Memory Tracker
数据库的内存管理是数据库内核设计中的重要模块,内存的可度量.可管控是数据库稳定性的重要保障.同样的,内存管理对图数据库 NebulaGraph 也至关重要. 图数据库的多度关联查询特性,往往使图数据库 ...
- git解决一个电脑多用户情况(win7)
首先:在输入ssh-keygen -t rsa -C "注册邮箱"后不要急着按enter,此时输入秘钥对的文件名,不要跟默认文件重名(默认的是id_rsa)
- 如何让ChatGPT生成Midjourney提示词
导读:最近AI绘画非常的火,今天我们看ChatGPT如何生成Midjourney提示词,让AI教AI做事. 本文字数:900,阅读时长大约:3分钟 正如 Midjourney 的官方网站报道的那样 ...
- js 之二 事件对象
事件对象 /当事件的响应函数被触发时,浏览器每次都会讲一个事件对象作为实参传递响应函数; 在事件对象中封装了当前事件相关的一切信息,比如:鼠标的,键盘的操作 // 当鼠标在areaDiv中移动时,在s ...
- 生信入门必须掌握的 30 个 Linux 命令
学习生物信息,Linux 是必须掌握的内容,其实常用的 Linux 命令也就 30 个左右,而且这些命令都是单词的简写,记忆起来并不困难.这里列出了常用的 30 个命令. 1. cd Change d ...
- IDEA连接数据库
我只想卷死各位,或者被各位卷死 在入门案例映射配置文件中存在报红的情况.问题如下: 产生的原因:Idea和数据库没有建立连接,不识别表信息.但是大家一定要记住,它并不影响程序的执行. 解决方式:在Id ...