[alibaba/druid]fix #5220 shrink方法keeplive bug

2025-11-10 721 views
9

修复 [DruidDataSource.java] shrink 方法中 keeplive的一个bug 导致数据库连接不断增多 #5220

System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount); Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);

shrink方法中这两行代码从connections[]数组移除的数据库连接,和shrink方法中这两行代码上面的添加到keepAliveConnections[]数组中的连接不一致

异常结果:

正常的连接引用直接丢失,也就是既不在connections[]数组,也不在keepAliveConnections[]数组 会不断触发新建数据库连接,导致泄露

解决办法:

在将连接添加到keepAliveConnections[]数组之后,立即将connections[]数组对应的连接置为null 最后在处理下connections[]数组,将null元素往后排整理下即可;

经过验证,连接恢复正常

回答

6

为啥保活要把lastActiveTimeMillis重置了,这样会不会绕过回收的逻辑,导致每次shrink的时候连接都不被释放呢?

3

为啥保活要把lastActiveTimeMillis重置了,这样会不会绕过回收的逻辑,导致每次shrink的时候连接都不被释放呢? long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis; 保活的逻辑是计算idleMillis是否超过keepAliveBetweenTimeMillis,如果不重置的话,这个连接会一直被保活

8

它原先逻辑是先计算当前连接空闲的时间idleMills,并判断idleMillis是否大于minEvictableIdleTimeMillis或者maxEvictableIdleTimeMillis,从而确定要不要废弃,如果不需要废弃才会去判断是否需要保活。 现在你的代码里是在保活时会重置lastActiveTimeMillis,那这个连接保活之后,不就走不到上面那两个判断里了么,这样它后面就一直是--保活--过了一段时间--再次保活循环了。我目前想的是这样,不知道有没有啥漏洞…… 我理解之前旧代码里保活没有重置连接活跃的时间,是考虑保活只是检测连接是否可用,而保活应该是不算用户的使用的,因此用户设置的minEvictableIdleTimeMillis这些空闲较久就丢弃连接的参数不应该被内部的保活策略来干扰吧。