mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add more onFatalError info.
This commit is contained in:
@@ -256,6 +256,9 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
protected boolean initGlobalVariants = false;
|
||||
protected volatile boolean onFatalError = false;
|
||||
protected volatile int onFatalErrorMaxActive = 0;
|
||||
protected volatile long lastFatalErrorTimeMillis = 0;
|
||||
protected volatile String lastFatalErrorSql = null;
|
||||
protected volatile Throwable lastFatalError = null;
|
||||
|
||||
protected static AtomicIntegerFieldUpdater<DruidAbstractDataSource> directCreateCountUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, "directCreateCount");
|
||||
protected static AtomicIntegerFieldUpdater<DruidAbstractDataSource> createCountUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, "creatingCount");
|
||||
@@ -1493,8 +1496,11 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void handleConnectionException(DruidPooledConnection pooledConnection, Throwable t)
|
||||
throws SQLException;
|
||||
public void handleConnectionException(DruidPooledConnection conn, Throwable t) throws SQLException {
|
||||
handleConnectionException(conn, t, null);
|
||||
}
|
||||
|
||||
public abstract void handleConnectionException(DruidPooledConnection conn, Throwable t, String sql) throws SQLException;
|
||||
|
||||
protected abstract void recycle(DruidPooledConnection pooledConnection) throws SQLException;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.security.PrivilegedAction;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -1416,7 +1416,20 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
&& onFatalErrorMaxActive > 0
|
||||
&& activeCount >= onFatalErrorMaxActive) {
|
||||
connectErrorCountUpdater.incrementAndGet(this);
|
||||
throw new SQLException("onFatalError, activeCount " + activeCount + ", onFatalErrorMaxActive " + onFatalErrorMaxActive);
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String errorMsg = "onFatalError, activeCount " + activeCount
|
||||
+ ", onFatalErrorMaxActive " + onFatalErrorMaxActive;
|
||||
|
||||
if (lastFatalErrorTimeMillis > 0) {
|
||||
errorMsg += ", time '" + format.format(new Date(lastFatalErrorTimeMillis)) + "'";
|
||||
}
|
||||
|
||||
if (lastFatalErrorSql != null) {
|
||||
errorMsg += ", sql \n" + lastFatalErrorSql;
|
||||
}
|
||||
|
||||
throw new SQLException(errorMsg, lastFatalError);
|
||||
}
|
||||
|
||||
connectCount++;
|
||||
@@ -1498,7 +1511,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
return poolalbeConnection;
|
||||
}
|
||||
|
||||
public void handleConnectionException(DruidPooledConnection pooledConnection, Throwable t) throws SQLException {
|
||||
public void handleConnectionException(DruidPooledConnection pooledConnection, Throwable t, String sql) throws SQLException {
|
||||
final DruidConnectionHolder holder = pooledConnection.getConnectionHolder();
|
||||
|
||||
errorCount.incrementAndGet();
|
||||
@@ -1516,45 +1529,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
|
||||
// exceptionSorter.isExceptionFatal
|
||||
if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) {
|
||||
if (pooledConnection.isTraceEnable()) {
|
||||
activeConnectionLock.lock();
|
||||
try {
|
||||
if (pooledConnection.isTraceEnable()) {
|
||||
activeConnections.remove(pooledConnection);
|
||||
pooledConnection.setTraceEnable(false);
|
||||
}
|
||||
} finally {
|
||||
activeConnectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
boolean requireDiscard = false;
|
||||
final ReentrantLock lock = pooledConnection.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if ((!pooledConnection.isClosed()) || !pooledConnection.isDisable()) {
|
||||
holder.setDiscard(true);
|
||||
pooledConnection.disable(t);
|
||||
requireDiscard = true;
|
||||
}
|
||||
|
||||
onFatalError = true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
if (requireDiscard) {
|
||||
if (holder.statementTrace != null) {
|
||||
for (Statement stmt : holder.statementTrace) {
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
this.discardConnection(holder.getConnection());
|
||||
holder.setDiscard(true);
|
||||
}
|
||||
|
||||
LOG.error("discard connection", sqlEx);
|
||||
handleFatalError(pooledConnection, sqlEx, sql);
|
||||
}
|
||||
|
||||
throw sqlEx;
|
||||
@@ -1563,6 +1538,58 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
}
|
||||
|
||||
protected final void handleFatalError(DruidPooledConnection conn, SQLException error, String sql) throws SQLException {
|
||||
final DruidConnectionHolder holder = conn.holder;
|
||||
|
||||
if (conn.isTraceEnable()) {
|
||||
activeConnectionLock.lock();
|
||||
try {
|
||||
if (conn.isTraceEnable()) {
|
||||
activeConnections.remove(conn);
|
||||
conn.setTraceEnable(false);
|
||||
}
|
||||
} finally {
|
||||
activeConnectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
long lastErrorTimeMillis = this.lastErrorTimeMillis;
|
||||
if (lastErrorTimeMillis == 0) {
|
||||
lastErrorTimeMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
boolean requireDiscard = false;
|
||||
final ReentrantLock lock = conn.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
if ((!conn.isClosed()) || !conn.isDisable()) {
|
||||
holder.setDiscard(true);
|
||||
conn.disable(error);
|
||||
requireDiscard = true;
|
||||
}
|
||||
|
||||
lastFatalErrorTimeMillis = lastErrorTimeMillis;
|
||||
onFatalError = true;
|
||||
lastFatalError = error;
|
||||
lastFatalErrorSql = sql;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
if (requireDiscard) {
|
||||
if (holder.statementTrace != null) {
|
||||
for (Statement stmt : holder.statementTrace) {
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
this.discardConnection(holder.getConnection());
|
||||
holder.setDiscard(true);
|
||||
}
|
||||
|
||||
LOG.error("discard connection", error);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回收连接
|
||||
*/
|
||||
|
||||
@@ -121,12 +121,16 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
}
|
||||
|
||||
public SQLException handleException(Throwable t) throws SQLException {
|
||||
return handleException(t, null);
|
||||
}
|
||||
|
||||
public SQLException handleException(Throwable t, String sql) throws SQLException {
|
||||
final DruidConnectionHolder holder = this.holder;
|
||||
|
||||
//
|
||||
if (holder != null) {
|
||||
DruidAbstractDataSource dataSource = holder.getDataSource();
|
||||
dataSource.handleConnectionException(this, t);
|
||||
dataSource.handleConnectionException(this, t, sql);
|
||||
}
|
||||
|
||||
if (t instanceof SQLException) {
|
||||
@@ -151,7 +155,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
rawStatement.clearParameters();
|
||||
} catch (SQLException ex) {
|
||||
this.handleException(ex);
|
||||
this.handleException(ex, null);
|
||||
if (rawStatement.getConnection().isClosed()) {
|
||||
return;
|
||||
}
|
||||
@@ -184,7 +188,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
//In this case, the exception is desired to be properly handled to remove the unusable connection from the pool.
|
||||
stmt.closeInternal();
|
||||
} catch (SQLException ex) {
|
||||
this.handleException(ex);
|
||||
this.handleException(ex, null);
|
||||
throw ex;
|
||||
} finally {
|
||||
holder.getDataSource().incrementClosedPreparedStatementCount();
|
||||
@@ -345,7 +349,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +388,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
resultSetConcurrency));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +423,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
resultSetHoldability));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +454,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, columnIndexes));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +485,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, columnNames));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +516,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, autoGeneratedKeys));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +549,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
stmtHolder = new PreparedStatementHolder(key, conn.prepareCall(sql));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +584,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
resultSetHoldability));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +617,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
conn.prepareCall(sql, resultSetType, resultSetConcurrency));
|
||||
holder.getDataSource().incrementPreparedStatementCount();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,7 +639,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
stmt = conn.createStatement();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmt);
|
||||
@@ -655,7 +659,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
stmt = conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmt);
|
||||
@@ -674,7 +678,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
stmt = conn.createStatement(resultSetType, resultSetConcurrency);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
|
||||
holder.getDataSource().initStatement(this, stmt);
|
||||
@@ -708,7 +712,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
conn.setAutoCommit(autoCommit);
|
||||
holder.setUnderlyingAutoCommit(autoCommit);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,7 +748,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.commit();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
} finally {
|
||||
handleEndTransaction(dataSource, null);
|
||||
}
|
||||
@@ -776,7 +780,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.rollback();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
} finally {
|
||||
handleEndTransaction(dataSource, null);
|
||||
}
|
||||
@@ -789,7 +793,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
return conn.setSavepoint(name);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
return null; // never arrive
|
||||
}
|
||||
}
|
||||
@@ -806,7 +810,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.rollback(savepoint);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
} finally {
|
||||
handleEndTransaction(dataSource, savepoint);
|
||||
}
|
||||
@@ -831,7 +835,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.releaseSavepoint(savepoint);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,7 +846,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
return conn.createClob();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
return null; // never arrive
|
||||
}
|
||||
}
|
||||
@@ -885,7 +889,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.setReadOnly(readOnly);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
|
||||
holder.setUnderlyingReadOnly(readOnly);
|
||||
@@ -905,7 +909,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.setCatalog(catalog);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +934,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.setTransactionIsolation(level);
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
holder.setUnderlyingTransactionIsolation(level);
|
||||
}
|
||||
@@ -955,7 +959,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
conn.clearWarnings();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,7 +1010,7 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.
|
||||
try {
|
||||
return conn.setSavepoint();
|
||||
} catch (SQLException ex) {
|
||||
handleException(ex);
|
||||
handleException(ex, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ public class DruidPooledPreparedStatement extends DruidPooledStatement implement
|
||||
currentFetchSize = defaultFetchSize;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.conn.handleException(e);
|
||||
this.conn.handleException(e, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,13 +66,25 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
}
|
||||
|
||||
protected SQLException checkException(Throwable error) throws SQLException {
|
||||
String sql = null;
|
||||
if (this instanceof DruidPooledPreparedStatement) {
|
||||
sql = ((DruidPooledPreparedStatement) this).getSql();
|
||||
}
|
||||
|
||||
handleScoketTimeout(error);
|
||||
|
||||
exceptionCount++;
|
||||
return conn.handleException(error);
|
||||
return conn.handleException(error, sql);
|
||||
}
|
||||
|
||||
private void handleScoketTimeout(Throwable error) throws SQLException {
|
||||
protected SQLException checkException(Throwable error, String sql) throws SQLException {
|
||||
handleScoketTimeout(error);
|
||||
|
||||
exceptionCount++;
|
||||
return conn.handleException(error, sql);
|
||||
}
|
||||
|
||||
protected void handleScoketTimeout(Throwable error) throws SQLException {
|
||||
if (this.conn == null
|
||||
|| this.conn.transactionInfo != null
|
||||
|| this.conn.holder == null) {
|
||||
@@ -228,7 +240,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -247,7 +259,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -298,7 +310,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -317,7 +329,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -336,7 +348,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -355,7 +367,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -374,7 +386,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -393,7 +405,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
} finally {
|
||||
conn.afterExecute();
|
||||
}
|
||||
@@ -547,7 +559,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
} catch (Throwable t) {
|
||||
errorCheck(t);
|
||||
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,7 +689,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
try {
|
||||
stmt.addBatch(sql);
|
||||
} catch (Throwable t) {
|
||||
throw checkException(t);
|
||||
throw checkException(t, sql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user