最新項目中用的druid鏈接數據庫遇到一個困擾好久的問題mysql
1 開始用的druid版本是1.1.22版本,因爲業務需求,單個鏈接須要執行好久,理論上不須要用到自動回收,但爲了安全,仍是加了自動回收,時間設置的2個小時。sql
問題來了,程序常常報The last packet successfully received from the server was XXXXX milliseconds ago. The last packet sent successfully to the server was 0 mill
iseconds ago錯誤,網上搜索了下答案,有說配置項,改數據庫事件設置,試過都沒有解決,後續看到https://cloud.tencent.com/developer/article/1397508 分析,以爲有必定道理,就開始後續之路數據庫
2.druid包升級到1.2.2,原來的問題是沒有了,新的問題出現了,discard long time none received connection,又繼續網上搜索答案,出來的結果一塌糊塗,不少說版本回退到1.1.22,內心不禁的說wc,這...安全
有點扯,繼續進行搜索測試,修改配置項validationQuery,修改testWhileIdle,修改...繼續測試,問題依舊,又搜索到運行時添加druid.mysql.usePingMethod=false,可是沒說怎樣添加,沒辦法下載源碼進行查看,導入源碼後發現以下:ide
if (valid && isMySql) { // unexcepted branch long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn); if (lastPacketReceivedTimeMs > 0) { long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs; if (lastPacketReceivedTimeMs > 0 // && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) { discardConnection(holder); String errorMsg = "discard long time none received connection. " + ", jdbcUrl : " + jdbcUrl + ", version : " + VERSION.getVersionNumber() + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis; LOG.warn(errorMsg); return false; } } }
這在配置中加timeBetweenEvictionRunsMillis:1800000 就能夠了,我的理解是一次操做數據庫大於這個時間就會被清除,更直觀些就是查詢或其餘操做在數據庫執行時間,這裏單位是毫秒。測試
緊接着查看源碼druid.mysql.usePingMethod=false這個設置,既然網上有人說,就看看好使不,源碼以下:ui
configFromProperties(System.getProperties()); } @Override public void configFromProperties(Properties properties) { String property = properties.getProperty("druid.mysql.usePingMethod"); if ("true".equals(property)) { setUsePingMethod(true); } else if ("false".equals(property)) { setUsePingMethod(false); } }
druid加載System.getProperties(),查看屬性中的druid.mysql.usePingMethod的對應值,若是false,就不用ping方法,否者用ping方法,進一步查看不用ping方法就是用默認select 1,System.getProperties()查看了下通常是系統的一些參數,可是能夠put(key,value),程序啓動時間加載進去就能夠,項目中用到了定時器(根據本身項目寫就能夠,加載一次就ok了),就在初始化時間設置了具體值,代碼以下:spa
public void contextInitialized(ServletContextEvent arg0) { try { System.getProperties().put("druid.mysql.usePingMethod", "false"); // 獲取Scheduler實例 scheduler = new StdSchedulerFactory().getScheduler(); ...
而後取消timeBetweenEvictionRunsMillis設置進行測試,程序跑1個小時沒有任何問題,到此問題解決。code
druid我的使用總結:server
1.The last packet successfully received from the server was問題升級jar包,我是升級到1.2.2版本
2.discard long time none received connection問題不應程序狀況下設置timeBetweenEvictionRunsMillis參數(注意是毫秒),改程序下加System.getProperties().put("druid.mysql.usePingMethod", "false")
druid默認使用usePingMethod方法,此方法並不會更新鏈接返回時間,致使lastPacketReceivedTimeMs大於timeBetweenEvictionRunsMillis
網上其餘的方法感受要不理解太深,沒有給出具體實現,要不就是複製粘貼的,但願對遇到此問題的人有所幫助。