{"record":{"id":"a7fb8f876a9a5dd4","repo":"mybatis/mybatis-3","slug":"pooleddatasource-could-not-get-a-good-connection","errorCode":null,"errorMessage":"PooledDataSource: Could not get a good connection to the database.","messagePattern":"PooledDataSource: Could not get a good connection to the database\\.","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"critical","filePath":"src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java","lineNumber":532,"sourceCode":"            conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));\n            conn.setCheckoutTimestamp(System.currentTimeMillis());\n            conn.setLastUsedTimestamp(System.currentTimeMillis());\n            state.activeConnections.add(conn);\n            state.requestCount++;\n            state.accumulatedRequestTime += System.currentTimeMillis() - t;\n          } else {\n            if (log.isDebugEnabled()) {\n              log.debug(\"A bad connection (\" + conn.getRealHashCode()\n                  + \") was returned from the pool, getting another connection.\");\n            }\n            state.badConnectionCount++;\n            localBadConnectionCount++;\n            conn = null;\n            if (localBadConnectionCount > poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance) {\n              if (log.isDebugEnabled()) {\n                log.debug(\"PooledDataSource: Could not get a good connection to the database.\");\n              }\n              throw new SQLException(\"PooledDataSource: Could not get a good connection to the database.\");\n            }\n          }\n        }\n      } finally {\n        lock.unlock();\n      }\n\n    }\n\n    if (conn == null) {\n      if (log.isDebugEnabled()) {\n        log.debug(\"PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.\");\n      }\n      throw new SQLException(\n          \"PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.\");\n    }\n\n    return conn;","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/datasource/pooled/PooledDataSource.java#L514-L550","documentation":"PooledDataSource.popConnection() loops trying to obtain a usable connection. When it repeatedly gets connections that fail pingConnectionDB() validation ('bad connections'), it counts them; once localBadConnectionCount exceeds poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance (default tolerance 3), it throws SQLException 'PooledDataSource: Could not get a good connection to the database.' This means the pool can hand out connections but they are all broken.","triggerScenarios":"poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance consecutive connections fail the PoolState ping query (PoolPingEnabled / poolPingQuery); database restarted or network dropped while pooled connections remained cached; wrong poolPingQuery for the DB dialect; driver incompatibility making isValid()/ping fail; DB max_allowed_packet or firewall idle-killing connections faster than pings detect.","commonSituations":"Database failover/restart behind a load balancer leaving dead sockets in the pool; aggressive firewall/LB idle timeouts (e.g., 5 min) killing pooled connections; poolPingEnabled=false so dead connections are never validated; custom poolPingQuery that is not valid SQL on the target database; MySQL wait_timeout killing idle connections.","solutions":["Check that the database is actually reachable and up (the pool found connections but every one failed validation)","Enable connection validation: set poolPingEnabled=true, poolPingQuery to a cheap valid query (e.g., SELECT 1), and poolPingConnectionsNotUsedFor under the network/firewall idle timeout","Reduce idle connections: lower poolMaximumIdleConnections so fewer stale sockets are cached, and ensure poolMaximumActiveConnections sizing fits DB limits","If using a custom poolPingQuery, verify it executes on your DB; if the driver supports it, prefer JDBC isValid by leaving the default ping path","Raise poolMaximumLocalBadConnectionTolerance only as a stopgap; the root cause is dead connections in the pool"],"exampleFix":"<!-- before: no validation, dead connections stay in pool -->\n<dataSource type=\"POOLED\">\n  <property name=\"driver\" value=\"com.mysql.cj.jdbc.Driver\"/>\n  <property name=\"url\" value=\"jdbc:mysql://db:3306/app\"/>\n</dataSource>\n\n<!-- after -->\n<dataSource type=\"POOLED\">\n  <property name=\"driver\" value=\"com.mysql.cj.jdbc.Driver\"/>\n  <property name=\"url\" value=\"jdbc:mysql://db:3306/app\"/>\n  <property name=\"poolPingEnabled\" value=\"true\"/>\n  <property name=\"poolPingQuery\" value=\"select 1\"/>\n  <property name=\"poolPingConnectionsNotUsedFor\" value=\"60000\"/>\n  <property name=\"poolMaximumIdleConnections\" value=\"5\"/>\n</dataSource>","handlingStrategy":"retry","validationCode":"// Pre-flight check that the DB is reachable before pool use:\ntry (Connection c = pooledDataSource.getConnection()) {\n  if (!c.isValid(2)) throw new SQLException(\"DB unreachable\");\n}","typeGuard":null,"tryCatchPattern":"int attempts = 0;\nwhile (true) {\n  try (Connection c = pooledDataSource.getConnection()) {\n    return c.createStatement().executeQuery(q);\n  } catch (SQLException e) {\n    if (++attempts >= 3 || !e.getMessage().contains(\"Could not get a good connection\")) throw e;\n    // pool is full of dead connections; wait for revalidation cycle\n  }\n}","preventionTips":["Enable poolPingEnabled with a valid poolPingQuery and a poolPingConnectionsNotUsedFor below your firewall idle timeout","Keep poolMaximumIdleConnections modest so fewer stale sockets accumulate","Align pool sizing with database and LB connection limits"],"tags":["mybatis","connection-pool","database-outage","validation","network"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}