1. 程式人生 > >資料庫連線池記憶體洩漏問題的分析和解決方案

資料庫連線池記憶體洩漏問題的分析和解決方案

## 一、問題描述 上週五晚上主營出現部分裝置掉線,經過檢視日誌發現是由於快取系統出現長時間gc導致的。這裡的gc日誌的特點是: - 1.gc時間都在2s以上,部分節點甚至出現12s超長時間gc。 - 2.同一個節點距離上次gc時間間隔為普遍為13~15天。 ![](https://user-gold-cdn.xitu.io/2020/5/3/171d9bfe5e82ffd7?w=553&h=383&f=png&s=217069) 然後緊急把剩餘未gc的一個節點記憶體dump下來,使用mat工具打開發現,com.mysql.jdbc.NonRegisteringDriver 物件佔了堆記憶體的大部分空間。 ![](https://user-gold-cdn.xitu.io/2020/4/19/1719258609a7d44a?w=553&h=197&f=png&s=94801) 檢視物件數量,發現com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference **這個物件堆積了10140 個**。 ![](https://user-gold-cdn.xitu.io/2020/4/19/171925addf1047c5?w=553&h=99&f=png&s=37925) 初步判斷長時間gc的問題應該是**由於 com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference 這個物件大量堆積引起的**。 ## 二、問題分析 目前正式環境使用資料庫相關依賴如下: 依賴| 版本 | -|-| mysql | 5.1.47 | hikari | 2.7.9 | Sharding-jdbc | 3.1.0 | 根據以上描述,提出以下問題: - 1、com.mysql.jdbc.NonRegisteringDriver$ConnectionPhantomReference 到底是個什麼物件呢? - 2、這種物件為什麼會大量堆積,JVM回收不過來了? ### NonRegisteringDriver$ConnectionPhantomReference 到底是個什麼物件呢? 簡單來說,NonRegisteringDriver類有個虛引用集合connectionPhantomRefs用於儲存所有的資料庫連線,NonRegisteringDriver.trackConnection方法負責把新建立的連線放入connectionPhantomRefs集合。原始碼如下: ``` 1.public class NonRegisteringDriver implements java.sql.Driver { 2. protected static final Concurren