Root Cause Analysis of MySQL 8.0 Driver Upgrade Causing Druid Connection Pool Blocking
After upgrading to MySQL 8.0, the Druid connection pool experiences severe performance degradation with many threads blocked due to repeated failed class loading of the removed MySQLConnection class, and the issue is resolved by upgrading Druid to a newer version.
Phenomenon : After upgrading the MySQL driver to 8.0, the Druid connection pool shows that most SQL execution times exceed 200 ms under high concurrency, and many threads become blocked.
Thread dump analysis reveals a BLOCKED state at com.alibaba.druid.util.Utils.loadClass(Utils.java:220):
"http-nio-5366-exec-48" #210 daemon prio=5 os_prio=0 tid=0x00000000023d0800 nid=0x3be9 waiting for monitor entry [0x00007fa4c1400000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:66)
- waiting to lock <0x0000000775af0960> (a java.lang.Object)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
at com.alibaba.druid.util.Utils.loadClass(Utils.java:220)
at com.alibaba.druid.util.MySqlUtils.getLastPacketReceivedTimeMs(MySqlUtils.java:372)Root Cause Analysis : The method MySqlUtils.getLastPacketReceivedTimeMs() tries to load the class com.mysql.jdbc.MySQLConnection. In MySQL 8.0 this class was renamed to com.mysql.cj.jdbc.ConnectionImpl, so the load fails. The utility method Utils.loadClass() catches ClassNotFoundException and returns null without propagating the error, causing the failure to be silent.
public class MySqlUtils {
public static long getLastPacketReceivedTimeMs(Connection conn) throws SQLException {
if (class_connectionImpl == null && !class_connectionImpl_Error) {
try {
class_connectionImpl = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
} catch (Throwable error) {
class_connectionImpl_Error = true;
}
}
// ... (omitted for brevity) ...
if (class_connectionImpl == null) {
return -1;
}
// further reflection logic ...
}
}The Utils.loadClass() implementation also swallows ClassNotFoundException:
public static Class<?> loadClass(String className) {
Class<?> clazz = null;
if (className == null) {
return null;
}
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
// skip
}
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
if (ctxClassLoader != null) {
try {
clazz = ctxClassLoader.loadClass(className);
} catch (ClassNotFoundException e) {
// skip
}
}
return clazz;
}Because the missing class is never reported, each call to getLastPacketReceivedTimeMs() repeatedly attempts to load com.mysql.jdbc.MySQLConnection. The loading is performed by TomcatEmbeddedWebappClassLoader, whose loadClass() method is synchronized:
public class TomcatEmbeddedWebappClassLoader extends ParallelWebappClassLoader {
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name)) {
Class<?> result = findExistingLoadedClass(name);
result = (result != null) ? result : doLoadClass(name);
if (result == null) {
throw new ClassNotFoundException(name);
}
return resolveIfNecessary(result, resolve);
}
}
}This synchronization creates a lock contention point; under high concurrency the repeated failed loads cause many threads to block, leading to the observed >200 ms latency.
When is the method invoked? The getLastPacketReceivedTimeMs() method is called from DruidAbstractDataSource.testConnectionInternal(), which is part of Druid's connection‑validation logic (parameters testOnBorrow, testOnReturn, testWhileIdle). With testOnBorrow=true, every connection acquisition triggers the costly class‑loading path, dramatically degrading performance.
Solution : The issue exists in Druid 1.x versions ≤ 1.1.22. Upgrading to Druid ≥ 1.1.23 or to any 1.2.x version eliminates the bug.
Reference: GitHub issue #3808 .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
