HikariPool-1 - Connection is not available, request timed out after 30000ms——數據庫事務與數據庫連接


線下Tomcat出現故障,查看日志報錯:

HikariPool-1 - Connection is not available, request timed out after 30000ms

最后調查的問題是:

某個Service中有個方法使用 httpclient 調用了一個外部接口,而當時這個外部接口服務出現故障,導致httpclient調用卡死了,一直沒有響應,因為在Service方法中,也就是在數據庫事務中,httpclient調用卡死導致 數據庫連接一直無法釋放,卡死的httpclient調用不斷的增大,數據庫連接不斷的被占用並且無法釋放,最終達到了最大值:

<!-- 連接池中允許的最大連接數。缺省值:10;推薦的公式:((core_count * 2) + effective_spindle_count) -->
<property name="maximumPoolSize" value="15" />

其他功能需要訪問數據庫時,就報錯:HikariPool-1 - Connection is not available, request timed out after 30000ms

這里問題的關鍵在於 不能在事務中調用外部接口,不能在事務中有耗時的操作等存在。這樣會導致事務變成大事務,長時間占用數據庫連接、有可能還導致事務長時間持有相關鎖從而導致死鎖。

最佳的解決辦法,自然是把 httpclient 外部調用移到事務外面。實時證明,移到事務外面就恢復正常了。

另外,httpclient 調用應該加上超時現在,比如超過2秒沒有返回,就斷開:

 URL url = new URL(urlAddress);
 URLConnection conn = url.openConnection();
 conn.setConnectTimeout(2000); 	// 2秒沒有連上,則超時
 conn.setReadTimeout(2000); 	// 2秒沒有響應,則超時

 

這樣也可以緩解問題。但是最好的方法還是把外部調用移到事務外面!

這里有個原理需要弄清楚:

service方法里面就是一個 httpclient 調用,沒有查詢數據庫,為什么還是 會占用數據庫連接呢????

原因是 數據庫事務肯定是需要基於數據庫連接的!就行我們在mysql客戶端里面執行:begin transaction 命令一樣,先得連上mysql 。沒有連上mysql,無法開啟事務。

這也是為什么在 service方法里面沒有查詢mysql,但是還是會占用一個數據庫連接的原因所在。

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM