HikariCP不斷打印WARN日志Failed to validate connection com.mysql.jdbc.JDBC4Connection@xxxxx (...) Possibly consider using a shorter maxLifetime value.


最終解決方案(結論)

maxLifeTime參數需要設置為小於min(數據庫的wait_timeout,HA代理的超時時間,其他代理的超時時間);也就是說maxLifeTime不僅要像HikariCP官方說的那樣小於數據庫的wait_timeout,還要小於包括HA代理在內的所有介於數據庫和業務應用之間其他代理的超時時間。

起因

之前項目中用的都是c3p0的一些連接池,但是根據公司的提供,改為使用HikariCP連接池。但是在項目運行過程中發現項目總是過一段時間就打印日志:

Failed to validate connection com.mysql.jdbc.JDBC4Connection@xxxxx (...)Possibly consider using a shorter maxLifetime value.

解決過程

經過排查和觀看源代碼,可以發現這個日志實際上並不會導致業務SQL語句的執行出現問題,但是終究還是對語句的執行速度有影響,通過拋出異常再重新獲取有效連接肯定是比直接獲取有效連接是要慢的。所以在有一些需求之間的空閑時間的情況下,還是打算排查一下這個問題。

按照HikariCP官方和日志中的建議來看,應該是maxLifeTime設置的過長了,所以在詢問過DBA之后,得知數據庫的wait_timeout設置的是500秒,所以將maxLifeTime連接設置為450_000毫秒,但是仍然還是會打印這種日志,所以這是不行的。

接下來我在網上搜,發現各種的解決都有,大部分都是通過設置更短的時間解決的,但是很少有說為什么設置的這么短就可以解決,而且每個人的數據庫配置都是不一樣的,所以實際上沒什么借鑒意義。那么還是要自己分析一下,可以確定的是出現問題的就是maxLifeTime這個參數。那么這個參數的作用是什么?通過閱讀部分HikariCP的源碼和對於網上說法的理解來說,maxLifeTime就是用於設置連接在連接池中生存的最大時間的,這個參數一般要比數據庫持有連接的時間要短。這是很好理解的,如果數據庫主動斷開連接,那么底層意義上,連接就已經失效了,一定是會打印這個日志的。但是我明明已經將maxLifeTime設置的比數據庫的wait_timeout要短了,然后我一度以為是不是DBA給了錯誤的timeout時間,向DBA確認之后發現不行。也就是說數據庫並不會在maxLifeTime的時間內斷開連接。

然后我在搜索的時候發現有一個結果是導向了GitHub的,我想到這個問題應該是很常見的,而且GitHub上作者也會那么我就到GitHub上HikariCP 的issue里面進行搜索,發現了這么一個issue,這個issue也有作者在里面回答,作者的回答主要是檢查mysql的連接時間和是否有獲取並自行關閉了底層的connection。這種情況在我這里都是沒有的。然后有一個人緊跟着作者說是否是HA代理超時了,然后我就想到我們的數據庫是有用到HA代理的,而且服務如果是通過HA代理連接數據庫的話,那么maxLifeTime一定是設置為比數據庫超時時間和HA代理超時時間中最小的那一個還要小。然后向DBA詢問HA代理的超時時間,說是300秒,后續我將maxLifeTime改為290_000毫秒之后,發現不再打印錯誤日志了,至此問題解決

可以很容易想到的是,如果服務與數據庫之間還隔了其他的服務或者代理的話,那么maxLifeTime也是取決於這些中間服務和數據庫中最小的那個超時時間的,但是maxLifeTime最小只能到30秒。


免責聲明!

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



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