connection holder is null

1 連接被回收

(1)錯誤日誌

Caused by: java.sql.SQLException: connection holder is null
at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1085)
at com.alibaba.druid.pool.DruidPooledConnection.getMetaData(DruidPooledConnection.java:825)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:285)
... 70 more
ERROR: (DruidDataSource.java:1815)   abandon connection, open stackTrace
at java.lang.Thread.getStackTrace(Thread.java:1588)
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:942)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4534)
at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:661)
at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4530)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:880)
at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)

(2)異常分析

由於connection holder is null,所以在druid的源碼中找有關連接的holder,在com.alibaba.druid.pool包下有一個DruidConnectionHolder,源碼如下圖

通過源碼結構可以判定DruidConnectionHolder是連接和事物的關聯,holder中持有一個連接。數據庫事物commit之前的所有操作都要基於同一個Connection,所以可以推斷出holder is null 就是連接被釋放了,根據詳細的異常堆信息    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:942)查看源碼

getConnectionDirect方法中有一段代碼會回收Connection,如下圖

決定是否回收Connection的條件是removeAbandoned, 然後把連接放到activeConnections中,然後在DruidConnectionHolder的init()方法中發現連接銷燬線程

如上圖 銷燬連接的方法判斷執行時間是否大於removeAbandonedTimeoutMillis,如果大於則銷燬然後發現項目中連接池參數設置配置瞭如下

<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>

開啓了removeAbandoned且設置了1分鐘,由於項目中執行了一個盤點的worker,時長較長執行邏輯超過設置的閥值,連接被釋放,觸發上面的異常。

(3) 解決方案

removeAbandoned和removeAbandonedTimeout的設計初衷是爲了防止連接泄露的情況發生,所以一定要配置

所以首先調長removeAbandonedTimeout時間,重新上線把中斷的業務跑過,

然後優化對應的執行邏輯,縮減運行時間,最終把時長設定在180秒(視業務而定)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章