mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
bug fixed for testWhileIdle.
This commit is contained in:
@@ -1295,6 +1295,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
Exception error = null;
|
||||
try {
|
||||
result = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
|
||||
} catch (SQLException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
error = ex;
|
||||
}
|
||||
@@ -1327,7 +1329,14 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
protected boolean testConnectionInternal(Connection conn) {
|
||||
return testConnectionInternal(null, conn);
|
||||
}
|
||||
|
||||
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
|
||||
String sqlFile = JdbcSqlStat.getContextSqlFile();
|
||||
String sqlName = JdbcSqlStat.getContextSqlName();
|
||||
|
||||
@@ -1339,7 +1348,28 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
}
|
||||
try {
|
||||
if (validConnectionChecker != null) {
|
||||
return validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
|
||||
boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
if (holder != null) {
|
||||
holder.lastValidTimeMillis = currentTimeMillis;
|
||||
}
|
||||
|
||||
if (valid && JdbcConstants.MYSQL_DRIVER.equals(driverClass)) { // unexcepted branch
|
||||
long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
|
||||
long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
|
||||
if (lastPacketReceivedTimeMs > 0 //
|
||||
&& mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
|
||||
discardConnection(conn);
|
||||
String errorMsg = "discard long time none received connection. "
|
||||
+ ", jdbcUrl : " + jdbcUrl
|
||||
+ ", jdbcUrl : " + jdbcUrl
|
||||
+ ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
|
||||
LOG.error(errorMsg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
if (conn.isClosed()) {
|
||||
@@ -1367,7 +1397,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
} catch (Throwable ex) {
|
||||
// skip
|
||||
return false;
|
||||
} finally {
|
||||
|
||||
@@ -51,6 +51,7 @@ public final class DruidConnectionHolder {
|
||||
protected final List<StatementEventListener> statementEventListeners = new CopyOnWriteArrayList<StatementEventListener>();
|
||||
protected final long connectTimeMillis;
|
||||
protected volatile long lastActiveTimeMillis;
|
||||
protected volatile long lastValidTimeMillis;
|
||||
private long useCount = 0;
|
||||
private long keepAliveCheckCount = 0;
|
||||
private long lastNotEmptyWaitNanos;
|
||||
|
||||
@@ -23,17 +23,7 @@ import java.security.PrivilegedAction;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@@ -461,6 +451,17 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
String property = properties.getProperty("druid.initConnectionSqls");
|
||||
if (property != null && property.length() > 0) {
|
||||
try {
|
||||
StringTokenizer tokenizer = new StringTokenizer(property, ";");
|
||||
setConnectionInitSqls(Collections.list(tokenizer));
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.error("illegal property 'druid.initConnectionSqls'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isKillWhenSocketReadTimeout() {
|
||||
@@ -1175,27 +1176,39 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
return;
|
||||
}
|
||||
|
||||
String realDriverClassName = driver.getClass().getName();
|
||||
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|
||||
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
|
||||
this.exceptionSorter = new MySqlExceptionSorter();
|
||||
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
|
||||
this.exceptionSorter = new OracleExceptionSorter();
|
||||
} else if (realDriverClassName.equals("com.informix.jdbc.IfxDriver")) {
|
||||
this.exceptionSorter = new InformixExceptionSorter();
|
||||
|
||||
} else if (realDriverClassName.equals("com.sybase.jdbc2.jdbc.SybDriver")) {
|
||||
this.exceptionSorter = new SybaseExceptionSorter();
|
||||
for (Class<?> driverClass = driver.getClass();;) {
|
||||
String realDriverClassName = driverClass.getName();
|
||||
if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //
|
||||
|| realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) {
|
||||
this.exceptionSorter = new MySqlExceptionSorter();
|
||||
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
|
||||
this.exceptionSorter = new OracleExceptionSorter();
|
||||
} else if (realDriverClassName.equals("com.informix.jdbc.IfxDriver")) {
|
||||
this.exceptionSorter = new InformixExceptionSorter();
|
||||
|
||||
} else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)) {
|
||||
this.exceptionSorter = new PGExceptionSorter();
|
||||
} else if (realDriverClassName.equals("com.sybase.jdbc2.jdbc.SybDriver")) {
|
||||
this.exceptionSorter = new SybaseExceptionSorter();
|
||||
|
||||
} else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) {
|
||||
this.exceptionSorter = new MockExceptionSorter();
|
||||
} else if (realDriverClassName.contains("DB2")) {
|
||||
this.exceptionSorter = new DB2ExceptionSorter();
|
||||
} else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)) {
|
||||
this.exceptionSorter = new PGExceptionSorter();
|
||||
|
||||
} else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) {
|
||||
this.exceptionSorter = new MockExceptionSorter();
|
||||
} else if (realDriverClassName.contains("DB2")) {
|
||||
this.exceptionSorter = new DB2ExceptionSorter();
|
||||
|
||||
} else {
|
||||
Class<?> superClass = driverClass.getSuperclass();
|
||||
if (superClass != null && superClass != Object.class) {
|
||||
driverClass = superClass;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1244,7 +1257,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
|
||||
if (testOnBorrow) {
|
||||
boolean validate = testConnectionInternal(poolableConnection.conn);
|
||||
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
|
||||
if (!validate) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("skip not validate connection.");
|
||||
@@ -1275,25 +1288,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
if (idleMillis >= timeBetweenEvictionRunsMillis
|
||||
|| idleMillis < 0 // unexcepted branch
|
||||
) {
|
||||
boolean validate = testConnectionInternal(poolableConnection.conn);
|
||||
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
|
||||
if (!validate) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("skip not validate connection.");
|
||||
}
|
||||
|
||||
discardConnection(realConnection);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JdbcConstants.MYSQL_DRIVER.equals(driverClass)) { // unexcepted branch
|
||||
long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(realConnection);
|
||||
long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
|
||||
if (lastPacketReceivedTimeMs > 0 //
|
||||
&& mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
|
||||
discardConnection(realConnection);
|
||||
LOG.warn("discard long time none received connection. millis : " + mysqlIdleMillis);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1567,7 +1569,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
|
||||
if (testOnReturn) {
|
||||
boolean validate = testConnectionInternal(physicalConnection);
|
||||
boolean validate = testConnectionInternal(holder, physicalConnection);
|
||||
if (!validate) {
|
||||
JdbcUtils.close(physicalConnection);
|
||||
|
||||
|
||||
@@ -54,28 +54,23 @@ import com.alibaba.druid.support.logging.LogFactory;
|
||||
* @author wenshao [szujobs@hotmail.com]
|
||||
*/
|
||||
public class DruidPooledConnection extends PoolableWrapper implements javax.sql.PooledConnection, Connection {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class);
|
||||
|
||||
public static final int MAX_RECORD_SQL_COUNT = 10;
|
||||
|
||||
protected Connection conn;
|
||||
protected volatile DruidConnectionHolder holder;
|
||||
protected TransactionInfo transactionInfo;
|
||||
private final boolean dupCloseLogEnable;
|
||||
protected volatile boolean traceEnable = false;
|
||||
private boolean disable = false;
|
||||
private boolean closed = false;
|
||||
protected final Thread ownerThread;
|
||||
private long connectedTimeMillis;
|
||||
private long connectedTimeNano;
|
||||
private volatile boolean running = false;
|
||||
private volatile boolean abandoned = false;
|
||||
|
||||
protected StackTraceElement[] connectStackTrace;
|
||||
protected Throwable disableError = null;
|
||||
|
||||
public ReentrantLock lock = new ReentrantLock();
|
||||
private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class);
|
||||
public static final int MAX_RECORD_SQL_COUNT = 10;
|
||||
protected Connection conn;
|
||||
protected volatile DruidConnectionHolder holder;
|
||||
protected TransactionInfo transactionInfo;
|
||||
private final boolean dupCloseLogEnable;
|
||||
protected volatile boolean traceEnable = false;
|
||||
private boolean disable = false;
|
||||
private boolean closed = false;
|
||||
protected final Thread ownerThread;
|
||||
private long connectedTimeMillis;
|
||||
private long connectedTimeNano;
|
||||
private volatile boolean running = false;
|
||||
private volatile boolean abandoned = false;
|
||||
protected StackTraceElement[] connectStackTrace;
|
||||
protected Throwable disableError = null;
|
||||
public ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public DruidPooledConnection(DruidConnectionHolder holder){
|
||||
super(holder.getConnection());
|
||||
|
||||
@@ -262,13 +262,26 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
DruidConnectionHolder holder = conn.holder;
|
||||
DruidAbstractDataSource dataSource = holder.dataSource;
|
||||
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
long lastActiveTimeMillis = holder.lastActiveTimeMillis;
|
||||
long idleMillis = System.currentTimeMillis() - lastActiveTimeMillis;
|
||||
long idleMillis = currentTimeMillis - lastActiveTimeMillis;
|
||||
long lastValidIdleMillis = currentTimeMillis - holder.lastActiveTimeMillis;
|
||||
|
||||
LOG.error("CommunicationsException, druid version " + VERSION.getVersionNumber()
|
||||
String errorMsg = "CommunicationsException, druid version " + VERSION.getVersionNumber()
|
||||
+ ", jdbcUrl : " + dataSource.jdbcUrl
|
||||
+ ", testWhileIdle " + dataSource.testWhileIdle
|
||||
+ ", idle millis " + idleMillis);
|
||||
+ ", idle millis " + idleMillis
|
||||
+ ", minIdle " + dataSource.minIdle
|
||||
+ ", poolingCount " + dataSource.getPoolingCount()
|
||||
+ ", timeBetweenEvictionRunsMillis " + dataSource.timeBetweenEvictionRunsMillis
|
||||
+ ", lastValidIdleMillis " + lastValidIdleMillis
|
||||
+ ", driver " + dataSource.driver.getClass().getName();
|
||||
|
||||
if (dataSource.exceptionSorter != null) {
|
||||
errorMsg += ", exceptionSorter " + dataSource.exceptionSorter.getClass().getName();
|
||||
}
|
||||
|
||||
LOG.error(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -16,9 +16,11 @@
|
||||
package com.alibaba.druid.pool.vendor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -101,7 +103,15 @@ public class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter i
|
||||
validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
|
||||
}
|
||||
|
||||
ping.invoke(conn, true, validationQueryTimeout * 1000);
|
||||
try {
|
||||
ping.invoke(conn, true, validationQueryTimeout * 1000);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof SQLException) {
|
||||
throw (SQLException) cause;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user