一.背景
應用在執行完某個復雜業務,主要包含20幾個查詢SQL的操作后,會導致數據庫連接池一直升高
druid版本:1.2.11
druid配置文件:
spring.datasource.druid.maxActive=100 spring.datasource.druid.initialSize=20 spring.datasource.druid.maxWait=6000 spring.datasource.druid.minIdle=20 spring.datasource.druid.timeBetweenEvictionRunsMillis=6000 spring.datasource.druid.keepAlive=true spring.datasource.druid.minEvictableIdleTimeMillis=30000 spring.datasource.druid.validationQuery=select 1 from dual spring.datasource.druid.testWhileIdle=true spring.datasource.druid.testOnBorrow=false spring.datasource.druid.testOnReturn=false spring.datasource.druid.poolPreparedStatements=true spring.datasource.druid.maxOpenPreparedStatements=20
二.排查過程
logging.level.com.alibaba.druid=debug
打開druid debug日志,發現如下報錯
3.進行本地調試跟蹤發現druid 的shrink 方法在保活處理時存在問題。
System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
shrink方法中這兩行代碼從connections[]數組移除的數據庫連接,和shrink方法中這兩行代碼上面的添加到keepAliveConnections[]數組中的連接不一致
異常結果:
- 正常的連接引用直接丟失,也就是既不在connections[]數組,也不在keepAliveConnections[]數組
- 會不斷觸發新建數據庫連接,導致泄露
三.解決方案
1.關閉keepAlive
2.升級Druid版本到1.2.20