[alibaba/druid]偶发连接失效java.sql.SQLException: connection disabled

2023-12-08 855 views
8

访问mysql过程中会突然出现 异常日志一: DruidPooledStatement errorCheck:CommunicationsException,druid version 1.1.23 然后报出异常日志二: discard connection com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 5,538,582 milliseconds ago. The last packet sent successfully to the server was 5,538,582 milliseconds ago.  …… Caused by: java.net.SocketException: Connection reset at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:115) 

后续有请求还偶尔报出 Cause: java.sql.SQLException: connection disabled ; uncategorized SQLException; SQL state [null]; error code [0]; connection disabled; nested exception is java.sql.SQLException: connection disabled at …… Caused by: java.sql.SQLException: connection disabled at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1169) at …… Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 5,538,582 milliseconds ago. The last packet sent successfully to the server was 5,538,582 milliseconds ago. …… Caused by: java.net.SocketException: Connection reset at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:115) at ……

配置: spring: datasource: druid: max-active: 10 min-idle: 0 max-wait: 5000 validation-query: select 1 testOn-borrow: true

回答

3

... received from the server was 5,538,582 milliseconds ago. 为什么不同时间点报错的5,538,582 这个数值是不变的,mysql服务端的空闲超时时间是24小时。个人理解min-idle设置为0后,那么所有的连接在空闲30min应该都被清除的,而5,538,582是否表示该连接空闲已经超过30min

9

druid的shrink清理连接处理逻辑有问题,我们自己打了个补丁,可以参考一下: https://github.com/alibaba/druid/pull/4726 建议你们先升一下druid版本,新版本修复了很多issue。

你们应该检查一下应用和数据库之间的网络设备配置,这种30分钟就断开连接的现象多是防火墙自动reset了空闲tcp连接超过30分钟导致的,要保活druid需要设置keepAlive=true

0

@zrlw 已经升级到druid 1.2.6版本,keep-alive也打开了,但还是出现Cause: java.sql.SQLException: connection disabled ... Communications link failure The last packet successfully received from the server was 11,700,370 milliseconds ago.这类的错误,每天能有几例错误,并且每次错误都是11,700,370 这个值,请问下这个是什么原因 max-active: 10 min-idle: 0 max-wait: 2000 validation-query: select 1 min-evictable-idle-time-millis: 600000 max-evictable-idle-time-millis: 1800000 keep-alive: true

8

公司内部很多服务都是使用druid,只有一个服务会产生这样的错误

2

我也遇到了相同的问题,目前版本1.2.16,后面有修复吗

8

没有解决,使用了推荐的补丁版本依旧会报错

0

得了,咱也没时间看源码去了,切回到Hikari连接池了

3

收到,我计划在5.1期间处理这个问题

4

11,700,370ms是3小时15分钟,之前你写的5,538,582ms是30分钟, 用的是mysql驱动么?如果是,druid发送的保活探测报文并不是你们配置的select 1,而是自动改为mysql的ping探活包,有开源或商业数据库(客户端用的mysql驱动)收到这种探活包不会更新服务端的连接状态,连接的空闲时间依然会增长,空闲超过阈值后还会主动拆连,建议你们的应用启动参数增加这个选项试试看(关掉druid默认的ping探活方法,采用普通的select语句探活): -Ddruid.mysql.usepingmethod=false

你们说的情况应该是探活机制失效的问题,我们自己打的那个补丁 https://github.com/alibaba/druid/pull/4726 只是修补druid连接池shrink清理逻辑,避免出现有效连接被待清理的无效连接覆盖掉、失效连接没有关闭直接进入老年代(连接泄露)的问题,并不能解决连接被数据库服务端或中间的网络设备直接干掉的情况。

0

另外如果配置了timeBetweenEvictionRunsMillis(druid执行清理连接、探活连接的destroy任务的时间间隔,默认1分钟)、keepAliveBetweenTimeMillis(空闲超过此配置的连接才会做探活处理,默认2分钟)这两个参数,也要确认一下不能配大了。

4

使用的是mysql的驱动,timeBetweenEvictionRunsMillis配置的是2秒,keepAliveBetweenTimeMillis没有配置,使用的应该是默认的时间,在druid提供监控的页面能看到有配置的探活sql在执行,我试过将mysql的主动关闭空闲连接的时间设置为30s进行测试,没有复现出这个问题

3

以下是设置的druid配置: spring: datasource: druid: max-active: 10 min-idle: 0 max-wait: 2000 validation-query: select 1 min-evictable-idle-time-millis: 600000 max-evictable-idle-time-millis: 1800000 keep-alive: true 并且在启动类中设置了 System.setProperty("druid.mysql.usePingMethod", "false");使用select 1进行探活

使用的mysql驱动是:com.mysql.jdbc.Driver

1

我们所使用的云厂商提供的k8s到mysql的连接确实经常会不稳定,造成连接失效,但是已经配置了通过select 1探活

2

你说的30秒是mysql数据库服务器的wait_timeout连接最大空闲时间么?如果keepAliveBetweenTimeMillis超过wait_timeout,那么druid的keepAlive探活机制应该是没有效果的,因为等不到druid发送探活包,服务端就已经判定连接空闲超过wait_timeout关闭连接了。

2

如果网络不稳定,探活也不一定保证池子里的连接都是可用的。探活检测默认的间隔时间是2分钟,两次检测中的时间窗可能就有连接被干掉了,此时如果从池子取到这种连接还是会报错的。 你说的只有一个服务存在这个问题,可以试试把那个服务的Druid选项testOnBorrow设为true看看能否减少这种问题(但并不能杜绝,如果网络很差,即使testOnBorrow检测成功,但下一秒也可能因网络中断而异常,还是会提示通信故障)。 另外testOnBorrow设为true也很影响性能,对于性能要求比较高的应用而言,不应该采用这种方式。

你说用了推荐的补丁版本依旧会报错,如果是我说的补丁 https://github.com/alibaba/druid/pull/4726 ,那主要原因就不是druid清理连接shrink方法里的arraycopy问题了。

7

我们的原因找到了,是由于在事物内没有回滚导致的,麻烦了