Why Does Druid Throw “Connection Holder Is Null” and How to Fix It?
This article examines recurring “connection holder is null” errors in Druid’s connection pool, explains how the holder is assigned and cleared, analyzes two real‑world cases—long‑running transactions and killed connections—and offers practical configuration recommendations to prevent the issue.
System has encountered several “connection holder is null” problems; some resolved, some not.
First, Druid connection pool implementation:
DruidPooledConnection is a static proxy holding a ConnectionHolder; the holder contains the actual connection. Every database‑related method checks checkState() and throws “connection holder is null” if the holder is null.
The ConnectionHolder is set when Datasource.getConnection() retrieves a cached holder from the pool’s array. A new DruidPooledConnection wraps this holder, so each call gets a different proxy.
First occurrence: long‑running transaction exceeds 60 seconds
The holder is initially non‑null; the error appears when another thread nullifies it, typically after transaction commit. Druid’s “remove abandoned connection” feature can reclaim connections that haven’t been returned within the configured timeout (60 s in our case), causing the exception.
Recommendation: disable “remove abandoned” in production; optionally enable testOnBorrow. Do not enable testWhileIdle under high concurrency.
Second occurrence: DBA kills a long‑running transaction
The root cause of the long‑uncommitted transaction is still unknown; MySQL’s innodb_trx and lock tables show no clues.
When the connection is killed, the application sees errors such as:
Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure. The last packet successfully received from the server was 20,840 milliseconds ago. connection holder is nullThe first two indicate a broken TCP connection. Druid catches the exception, uses ExceptionSorter to decide if it’s recoverable. For unrecoverable errors, the connection is removed from the pool, but the conversion process itself may trigger “connection holder is null” because metadata retrieval requires a live connection.
Note that the “connection holder is null” exception is reported only once per failure, unlike the frequent occurrences in our project, whose cause remains unidentified.
Additional note: MySQL’s rollback_on_timeout defaults to off; it rolls back only the last statement on timeout. Usually the application should handle lock acquisition failures and invoke connection.rollback() when a transaction is active.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
