diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index 002a7dd462..4468011c8f 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -679,7 +679,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis); if (conn != null) { - conn.setConnectedTimeNano(System.nanoTime()); + conn.setConnectedTimeNano(); StatFilterContext.getInstance().pool_connection_open(); } diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 331e90a308..b0a5c1f47f 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -29,6 +29,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -49,7 +51,6 @@ import javax.sql.DataSource; import com.alibaba.druid.filter.Filter; import com.alibaba.druid.filter.FilterChainImpl; import com.alibaba.druid.filter.FilterManager; -import com.alibaba.druid.pool.DruidDataSource.ActiveConnectionTraceInfo; import com.alibaba.druid.pool.vendor.NullExceptionSorter; import com.alibaba.druid.proxy.jdbc.DataSourceProxy; import com.alibaba.druid.proxy.jdbc.TransactionInfo; @@ -57,7 +58,6 @@ import com.alibaba.druid.stat.JdbcDataSourceStat; import com.alibaba.druid.stat.JdbcStatManager; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; -import com.alibaba.druid.util.ConcurrentIdentityHashMap; import com.alibaba.druid.util.DruidPasswordCallback; import com.alibaba.druid.util.Histogram; import com.alibaba.druid.util.IOUtils; @@ -70,22 +70,22 @@ import com.alibaba.druid.util.StringUtils; */ public abstract class DruidAbstractDataSource extends WrapperAdapter implements DruidAbstractDataSourceMBean, DataSource, DataSourceProxy, Serializable { - private final static Log LOG = LogFactory.getLog(DruidAbstractDataSource.class); + private final static Log LOG = LogFactory.getLog(DruidAbstractDataSource.class); - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public final static int DEFAULT_INITIAL_SIZE = 0; - public final static int DEFAULT_MAX_ACTIVE_SIZE = 8; - public final static int DEFAULT_MAX_IDLE = 8; - public final static int DEFAULT_MIN_IDLE = 0; - public final static int DEFAULT_MAX_WAIT = -1; - public final static String DEFAULT_VALIDATION_QUERY = null; // - public final static boolean DEFAULT_TEST_ON_BORROW = true; - public final static boolean DEFAULT_TEST_ON_RETURN = false; - public final static boolean DEFAULT_WHILE_IDLE = false; - public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; - public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 30 * 1000; - public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; + public final static int DEFAULT_INITIAL_SIZE = 0; + public final static int DEFAULT_MAX_ACTIVE_SIZE = 8; + public final static int DEFAULT_MAX_IDLE = 8; + public final static int DEFAULT_MIN_IDLE = 0; + public final static int DEFAULT_MAX_WAIT = -1; + public final static String DEFAULT_VALIDATION_QUERY = null; // + public final static boolean DEFAULT_TEST_ON_BORROW = true; + public final static boolean DEFAULT_TEST_ON_RETURN = false; + public final static boolean DEFAULT_WHILE_IDLE = false; + public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L; + public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 30 * 1000; + public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3; /** * The default value for {@link #getMinEvictableIdleTimeMillis}. @@ -93,133 +93,137 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements * @see #getMinEvictableIdleTimeMillis * @see #setMinEvictableIdleTimeMillis */ - public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; + public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L; - protected volatile boolean defaultAutoCommit = true; - protected volatile Boolean defaultReadOnly; - protected volatile Integer defaultTransactionIsolation; - protected volatile String defaultCatalog = null; + protected volatile boolean defaultAutoCommit = true; + protected volatile Boolean defaultReadOnly; + protected volatile Integer defaultTransactionIsolation; + protected volatile String defaultCatalog = null; - protected String name; + protected String name; - protected volatile String username; - protected volatile String password; - protected volatile String jdbcUrl; - protected volatile String driverClass; - protected volatile ClassLoader driverClassLoader; - protected volatile Properties connectProperties = new Properties(); + protected volatile String username; + protected volatile String password; + protected volatile String jdbcUrl; + protected volatile String driverClass; + protected volatile ClassLoader driverClassLoader; + protected volatile Properties connectProperties = new Properties(); - protected volatile PasswordCallback passwordCallback; - protected volatile NameCallback userCallback; + protected volatile PasswordCallback passwordCallback; + protected volatile NameCallback userCallback; - protected volatile int initialSize = DEFAULT_INITIAL_SIZE; - protected volatile int maxActive = DEFAULT_MAX_ACTIVE_SIZE; - protected volatile int minIdle = DEFAULT_MIN_IDLE; - protected volatile int maxIdle = DEFAULT_MAX_IDLE; - protected volatile long maxWait = DEFAULT_MAX_WAIT; + protected volatile int initialSize = DEFAULT_INITIAL_SIZE; + protected volatile int maxActive = DEFAULT_MAX_ACTIVE_SIZE; + protected volatile int minIdle = DEFAULT_MIN_IDLE; + protected volatile int maxIdle = DEFAULT_MAX_IDLE; + protected volatile long maxWait = DEFAULT_MAX_WAIT; - protected volatile String validationQuery = DEFAULT_VALIDATION_QUERY; - protected volatile int validationQueryTimeout = -1; - private volatile boolean testOnBorrow = DEFAULT_TEST_ON_BORROW; - private volatile boolean testOnReturn = DEFAULT_TEST_ON_RETURN; - private volatile boolean testWhileIdle = DEFAULT_WHILE_IDLE; - protected volatile boolean poolPreparedStatements = false; - protected volatile boolean sharePreparedStatements = false; - protected volatile int maxPoolPreparedStatementPerConnectionSize = 10; + protected volatile String validationQuery = DEFAULT_VALIDATION_QUERY; + protected volatile int validationQueryTimeout = -1; + private volatile boolean testOnBorrow = DEFAULT_TEST_ON_BORROW; + private volatile boolean testOnReturn = DEFAULT_TEST_ON_RETURN; + private volatile boolean testWhileIdle = DEFAULT_WHILE_IDLE; + protected volatile boolean poolPreparedStatements = false; + protected volatile boolean sharePreparedStatements = false; + protected volatile int maxPoolPreparedStatementPerConnectionSize = 10; - protected volatile boolean inited = false; + protected volatile boolean inited = false; - protected PrintWriter logWriter = new PrintWriter(System.out); + protected PrintWriter logWriter = new PrintWriter( + System.out); - protected List filters = new CopyOnWriteArrayList(); - protected volatile ExceptionSorter exceptionSorter = null; + protected List filters = new CopyOnWriteArrayList(); + protected volatile ExceptionSorter exceptionSorter = null; - protected Driver driver; + protected Driver driver; - protected volatile int queryTimeout; - protected volatile int transactionQueryTimeout; + protected volatile int queryTimeout; + protected volatile int transactionQueryTimeout; - protected AtomicLong createErrorCount = new AtomicLong(); + protected AtomicLong createErrorCount = new AtomicLong(); - protected long createTimespan; + protected long createTimespan; - protected volatile int maxWaitThreadCount = -1; + protected volatile int maxWaitThreadCount = -1; - protected volatile boolean accessToUnderlyingConnectionAllowed = true; + protected volatile boolean accessToUnderlyingConnectionAllowed = true; - protected volatile long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; + protected volatile long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; - protected volatile int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; + protected volatile int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN; - protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; + protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; - protected volatile boolean removeAbandoned; + protected volatile boolean removeAbandoned; - protected volatile long removeAbandonedTimeoutMillis = 300 * 1000; + protected volatile long removeAbandonedTimeoutMillis = 300 * 1000; - protected volatile boolean logAbandoned; + protected volatile boolean logAbandoned; - protected volatile int maxOpenPreparedStatements = -1; + protected volatile int maxOpenPreparedStatements = -1; - protected volatile List connectionInitSqls; + protected volatile List connectionInitSqls; - protected volatile String dbType; + protected volatile String dbType; - protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS; + protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS; - protected volatile ValidConnectionChecker validConnectionChecker = null; + protected volatile ValidConnectionChecker validConnectionChecker = null; - protected final AtomicLong errorCount = new AtomicLong(); - protected final AtomicLong dupCloseCount = new AtomicLong(); + protected final AtomicLong errorCount = new AtomicLong(); + protected final AtomicLong dupCloseCount = new AtomicLong(); - protected final ActiveConnectionTraceInfoMap activeConnections = new ActiveConnectionTraceInfoMap(); + protected final Map activeConnections = new IdentityHashMap(); + protected final static Object PRESENT = new Object(); - protected long id; + protected long id; - protected final Date createdTime = new Date(); - protected Date initedTime; + protected final Date createdTime = new Date(); + protected Date initedTime; - protected int connectionErrorRetryAttempts = 30; + protected int connectionErrorRetryAttempts = 30; - protected boolean breakAfterAcquireFailure = false; + protected boolean breakAfterAcquireFailure = false; - protected long transactionThresholdMillis = 0L; + protected long transactionThresholdMillis = 0L; - protected final AtomicLong commitCount = new AtomicLong(); - protected final AtomicLong startTransactionCount = new AtomicLong(); - protected final AtomicLong rollbackCount = new AtomicLong(); - protected final AtomicLong cachedPreparedStatementHitCount = new AtomicLong(); - protected final AtomicLong preparedStatementCount = new AtomicLong(); - protected final AtomicLong closedPreparedStatementCount = new AtomicLong(); - protected final AtomicLong cachedPreparedStatementCount = new AtomicLong(); - protected final AtomicLong cachedPreparedStatementDeleteCount = new AtomicLong(); - protected final AtomicLong cachedPreparedStatementMissCount = new AtomicLong(); + protected final AtomicLong commitCount = new AtomicLong(); + protected final AtomicLong startTransactionCount = new AtomicLong(); + protected final AtomicLong rollbackCount = new AtomicLong(); + protected final AtomicLong cachedPreparedStatementHitCount = new AtomicLong(); + protected final AtomicLong preparedStatementCount = new AtomicLong(); + protected final AtomicLong closedPreparedStatementCount = new AtomicLong(); + protected final AtomicLong cachedPreparedStatementCount = new AtomicLong(); + protected final AtomicLong cachedPreparedStatementDeleteCount = new AtomicLong(); + protected final AtomicLong cachedPreparedStatementMissCount = new AtomicLong(); - protected final Histogram transactionHistogram = new Histogram(10, 100, - 1000, - 10 * 1000, - 100 * 1000); + protected final Histogram transactionHistogram = new Histogram( + 10, + 100, + 1000, + 10 * 1000, + 100 * 1000); - private boolean dupCloseLogEnable = false; + private boolean dupCloseLogEnable = false; - private ObjectName objectName; + private ObjectName objectName; - private final AtomicLong executeCount = new AtomicLong(); + private final AtomicLong executeCount = new AtomicLong(); - protected volatile Throwable createError; - protected volatile Throwable lastError; - protected volatile long lastErrorTimeMillis; - protected volatile Throwable lastCreateError; - protected volatile long lastCreateErrorTimeMillis; + protected volatile Throwable createError; + protected volatile Throwable lastError; + protected volatile long lastErrorTimeMillis; + protected volatile Throwable lastCreateError; + protected volatile long lastCreateErrorTimeMillis; - protected boolean isOracle = false; + protected boolean isOracle = false; - protected boolean useOracleImplicitCache = true; + protected boolean useOracleImplicitCache = true; - protected final ReentrantLock lock; + protected final ReentrantLock lock; - protected AtomicLong createCount = new AtomicLong(); - protected AtomicLong destroyCount = new AtomicLong(); + protected AtomicLong createCount = new AtomicLong(); + protected AtomicLong destroyCount = new AtomicLong(); public DruidAbstractDataSource(boolean lockFair){ lock = new ReentrantLock(lockFair); @@ -1146,13 +1150,16 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements } public Set getActiveConnections() { - return this.activeConnections.keySet(); + synchronized (activeConnections) { + return new HashSet(this.activeConnections.keySet()); + } } public List getActiveConnectionStackTrace() { List list = new ArrayList(); - for (ActiveConnectionTraceInfo traceInfo : this.activeConnections.values()) { - list.add(IOUtils.toString(traceInfo.getStackTrace())); + + for (DruidPooledConnection conn : this.getActiveConnections()) { + list.add(IOUtils.toString(conn.getConnectStackTrace())); } return list; @@ -1505,9 +1512,5 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements to.useOracleImplicitCache = this.useOracleImplicitCache; } - // just for code format - public final static class ActiveConnectionTraceInfoMap extends ConcurrentIdentityHashMap { - } - public abstract void discardConnection(Connection realConnection); } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index f4e37a2c62..a0d9d2de04 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -680,9 +680,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (isRemoveAbandoned()) { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - activeConnections.put(poolalbeConnection, new ActiveConnectionTraceInfo(System.currentTimeMillis(), - stackTrace)); + poolalbeConnection.setConnectStackTrace(stackTrace); + poolalbeConnection.setConnectedTimeNano(); poolalbeConnection.setTraceEnable(true); + + synchronized (activeConnections) { + activeConnections.put(poolalbeConnection, PRESENT); + } } if (!this.isDefaultAutoCommit()) { @@ -791,7 +795,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat // exceptionSorter.isExceptionFatal if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) { if (pooledConnection.isTraceEnable()) { - activeConnections.remove(pooledConnection); + synchronized (activeConnections) { + activeConnections.remove(pooledConnection); + } } this.discardConnection(holder.getConnection()); pooledConnection.disable(); @@ -817,10 +823,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat final Connection physicalConnection = holder.getConnection(); if (pooledConnection.isTraceEnable()) { - ActiveConnectionTraceInfo oldInfo = activeConnections.remove(pooledConnection); - if (oldInfo == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); + synchronized (activeConnections) { + Object oldInfo = activeConnections.remove(pooledConnection); + if (oldInfo == null) { + if (LOG.isWarnEnabled()) { + LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); + } } } } @@ -1294,35 +1302,41 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public int removeAbandoned() { int removeCount = 0; - Iterator> iter = activeConnections.entrySet().iterator(); - - long currentMillis = System.currentTimeMillis(); + long currrentNanos = System.nanoTime(); List abandonedList = new ArrayList(); - for (; iter.hasNext();) { - Map.Entry entry = iter.next(); - DruidPooledConnection pooledConnection = entry.getKey(); + synchronized (activeConnections) { + Iterator iter = activeConnections.keySet().iterator(); - if (pooledConnection.isRunning()) { - continue; + for (; iter.hasNext();) { + DruidPooledConnection pooledConnection = iter.next(); + + if (pooledConnection.isRunning()) { + continue; + } + + long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000); + + if (timeMillis >= removeAbandonedTimeoutMillis) { + iter.remove(); + abandonedList.add(pooledConnection); + } } + } - ActiveConnectionTraceInfo activeInfo = entry.getValue(); - long timeMillis = currentMillis - activeInfo.getConnectTime(); - - if (timeMillis >= removeAbandonedTimeoutMillis) { + if (abandonedList.size() > 0) { + for (DruidPooledConnection pooledConnection : abandonedList) { JdbcUtils.close(pooledConnection); pooledConnection.abandond(); removeAbandonedCount++; removeCount++; - abandonedList.add(pooledConnection); if (isLogAbandoned()) { StringBuilder buf = new StringBuilder(); buf.append("abandon connection, open stackTrace\n"); - StackTraceElement[] trace = activeInfo.getStackTrace(); + StackTraceElement[] trace = pooledConnection.getConnectStackTrace(); for (int i = 0; i < trace.length; i++) { buf.append("\tat "); buf.append(trace[i].toString()); @@ -1334,11 +1348,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } - // multi-check dup close - for (DruidPooledConnection conn : abandonedList) { - activeConnections.remove(conn); - } - return removeCount; } @@ -1353,26 +1362,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return ref; } - static class ActiveConnectionTraceInfo { - - private final long connectTime; - private final StackTraceElement[] stackTrace; - - public ActiveConnectionTraceInfo(long connectTime, StackTraceElement[] stackTrace){ - super(); - this.connectTime = connectTime; - this.stackTrace = stackTrace; - } - - public long getConnectTime() { - return connectTime; - } - - public StackTraceElement[] getStackTrace() { - return stackTrace; - } - } - @Override public List getFilterClassNames() { List names = new ArrayList(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index 6ddfd4abd3..47085bfc96 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -70,6 +70,8 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec private volatile boolean abandoned = false; + private StackTraceElement[] connectStackTrace; + public DruidPooledConnection(DruidConnectionHolder holder){ this.conn = holder.getConnection(); this.holder = holder; @@ -81,10 +83,24 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec return ownerThread; } + public StackTraceElement[] getConnectStackTrace() { + return connectStackTrace; + } + + public void setConnectStackTrace(StackTraceElement[] connectStackTrace) { + this.connectStackTrace = connectStackTrace; + } + public long getConnectedTimeNano() { return connectedTimeNano; } + public void setConnectedTimeNano() { + if (connectedTimeNano <= 0) { + this.setConnectedTimeNano(System.nanoTime()); + } + } + public void setConnectedTimeNano(long connectedTimeNano) { this.connectedTimeNano = connectedTimeNano; } @@ -165,7 +181,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec public boolean isDisable() { return disable; } - + public void discard() { if (this.disable) { return; @@ -178,7 +194,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec } return; } - + holder.getDataSource().discardConnection(holder.getConnection()); } @@ -216,7 +232,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec if (this.disable) { return; } - + DruidConnectionHolder holder = this.holder; if (holder == null) { if (dupCloseLogEnable) { @@ -779,7 +795,7 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec return conn.isClosed(); } - + public boolean isAbandonded() { return this.abandoned; } diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java index 59ba9b58fd..671cd68690 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java +++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java @@ -134,7 +134,19 @@ public final class DruidStatManagerFacade { } public List> getSqlStatDataList(Integer dataSourceId) { - for (Object datasource : getDruidDataSourceInstances()) { + Set dataSources = getDruidDataSourceInstances(); + + if (dataSourceId == null) { + List> sqlList = new ArrayList>(); + + for (Object datasource : dataSources) { + sqlList.addAll(getSqlStatDataList(datasource)); + } + + return sqlList; + } + + for (Object datasource : dataSources) { if (dataSourceId != null && dataSourceId.intValue() != System.identityHashCode(datasource)) { continue; } @@ -147,7 +159,8 @@ public final class DruidStatManagerFacade { public List> getSqlStatDataList(Object datasource) { List> result = new ArrayList>(); - for (Object sqlStat : DruidDataSourceUtils.getSqlStatMap(datasource).values()) { + Map sqlStatMap = DruidDataSourceUtils.getSqlStatMap(datasource); + for (Object sqlStat : sqlStatMap.values()) { Map data = JdbcSqlStatUtils.getData(sqlStat); long executeCount = (Long) data.get("ExecuteCount"); diff --git a/src/test/java/com/alibaba/druid/bvt/stat/DruidStatServiceTest2.java b/src/test/java/com/alibaba/druid/bvt/stat/DruidStatServiceTest2.java index 383117aab5..eaa8263522 100644 --- a/src/test/java/com/alibaba/druid/bvt/stat/DruidStatServiceTest2.java +++ b/src/test/java/com/alibaba/druid/bvt/stat/DruidStatServiceTest2.java @@ -76,16 +76,18 @@ public class DruidStatServiceTest2 { PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); rs.next(); + Thread.sleep(1); rs.close(); stmt.close(); conn.close(); // second data source - String sql2 = "select 2"; + String sql2 = "select 1,1"; conn = dataSource2.getConnection(); stmt = conn.prepareStatement(sql2); rs = stmt.executeQuery(); rs.next(); + Thread.sleep(1); rs.close(); stmt.close(); conn.close();