diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 37aa44f54c..8197167758 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -97,6 +97,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements * @see #setMinEvictableIdleTimeMillis */ public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; + public static final long DEFAULT_PHY_TIMEOUT_MILLIS = 1000L * 60L * 60L * 7; protected volatile boolean defaultAutoCommit = true; protected volatile Boolean defaultReadOnly; @@ -159,6 +160,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; + protected volatile long phyTimeoutMillis = DEFAULT_PHY_TIMEOUT_MILLIS; + protected volatile boolean removeAbandoned; protected volatile long removeAbandonedTimeoutMillis = 300 * 1000; @@ -691,6 +694,14 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } + public long getPhyTimeoutMillis() { + return phyTimeoutMillis; + } + + public void setPhyTimeoutMillis(long phyTimeoutMillis) { + this.phyTimeoutMillis = phyTimeoutMillis; + } + public int getNumTestsPerEvictionRun() { return numTestsPerEvictionRun; } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index c3aa56b61b..5363815bb0 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -138,7 +138,7 @@ public class DruidDataSource extends DruidAbstractDataSource // threads private ScheduledFuture destroySchedulerFuture; - private DestroyTask destoryTask; + private DestroyTask destroyTask; private CreateConnectionThread createConnectionThread; private DestroyConnectionThread destroyConnectionThread; @@ -684,14 +684,14 @@ public class DruidDataSource extends DruidAbstractDataSource } protected void createAndStartDestroyThread() { - destoryTask = new DestroyTask(); + destroyTask = new DestroyTask(); if (destroyScheduler != null) { long period = timeBetweenEvictionRunsMillis; if (period <= 0) { period = 1000; } - destroySchedulerFuture = destroyScheduler.scheduleAtFixedRate(destoryTask, period, period, + destroySchedulerFuture = destroyScheduler.scheduleAtFixedRate(destroyTask, period, period, TimeUnit.MILLISECONDS); initedLatch.countDown(); return; @@ -1941,7 +1941,7 @@ public class DruidDataSource extends DruidAbstractDataSource break; } - destoryTask.run(); + destroyTask.run(); } catch (InterruptedException e) { break; } @@ -2031,8 +2031,8 @@ public class DruidDataSource extends DruidAbstractDataSource StringBuilder buf = new StringBuilder(); buf.append("abandon connection, owner thread: "); buf.append(pooledConnection.getOwnerThread().getName()); - buf.append(", connected time nano: "); - buf.append(pooledConnection.getConnectedTimeNano()); + buf.append(", connected at : "); + buf.append(pooledConnection.getConnectedTimeMillis()); buf.append(", open stackTrace\n"); StackTraceElement[] trace = pooledConnection.getConnectStackTrace(); @@ -2042,6 +2042,14 @@ public class DruidDataSource extends DruidAbstractDataSource buf.append("\n"); } + buf.append("ownerThread current state is "+pooledConnection.getOwnerThread().getState() + ", current stackTrace\n"); + trace = pooledConnection.getOwnerThread().getStackTrace(); + for (int i = 0; i < trace.length; i++) { + buf.append("\tat "); + buf.append(trace[i].toString()); + buf.append("\n"); + } + LOG.error(buf.toString()); } } @@ -2118,6 +2126,12 @@ public class DruidDataSource extends DruidAbstractDataSource for (int i = 0; i < checkCount; ++i) { DruidConnectionHolder connection = connections[i]; + long phyConnectTimeMillis = connection.getTimeMillis();//physical connection connected time + if( phyConnectTimeMillis > phyTimeoutMillis ){ + evictList.add(connection);//if physical connection connected greater than phyTimeoutMillis, close the connection, for mysql 8 hours timeout + continue; + } + if (checkTime) { long idleMillis = currentTimeMillis - connection.getLastActiveTimeMillis(); if (idleMillis >= minEvictableIdleTimeMillis) { diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceFactory.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceFactory.java index 95d32ab634..6fc306f8b9 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceFactory.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceFactory.java @@ -54,6 +54,7 @@ public class DruidDataSourceFactory implements ObjectFactory { public final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis"; public final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun"; public final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis"; + public final static String PROP_PHY_TIMEOUT_MILLIS = "phyTimeoutMillis"; public final static String PROP_TESTWHILEIDLE = "testWhileIdle"; public final static String PROP_PASSWORD = "password"; public final static String PROP_URL = "url"; @@ -233,6 +234,11 @@ public class DruidDataSourceFactory implements ObjectFactory { dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value)); } + value = (String) properties.get(PROP_PHY_TIMEOUT_MILLIS); + if (value != null) { + dataSource.setPhyTimeoutMillis(Long.parseLong(value)); + } + value = (String) properties.get(PROP_TESTWHILEIDLE); if (value != null) { dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue()); diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index b61fca779c..962872c896 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -65,7 +65,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. private boolean disable = false; private boolean closed = false; private final Thread ownerThread; - + private long connectedTimeMillis; private long connectedTimeNano; private volatile boolean running = false; @@ -82,6 +82,11 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. this.holder = holder; dupCloseLogEnable = holder.getDataSource().isDupCloseLogEnable(); ownerThread = Thread.currentThread(); + connectedTimeMillis = System.currentTimeMillis(); + } + + public long getConnectedTimeMillis() { + return connectedTimeMillis; } public Thread getOwnerThread() {