資料庫連線池記憶體洩漏問題的分析和解決方案
阿新 • • 發佈:2020-05-04
## 一、問題描述
上週五晚上主營出現部分裝置掉線,經過檢視日誌發現是由於快取系統出現長時間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