1、连接关闭
连接对象通过DruidPooledConnection 进行了包装,获取连接后都会进行连接的关闭或回收,如使用了类似 Mybatis、JPA 等开源框架通常会调用close方法,连接对象 DruidPooledConnection 重写了close()方法。
public void close() throws SQLException {
//已关闭状态
if (this.disable) {
return;
}
DruidConnectionHolder holder = this.holder;
if (holder == null) {
if (dupCloseLogEnable) {
LOG.error("dup close");
}
return;
}
DruidAbstractDataSource dataSource = holder.getDataSource();
//关闭连接的线程和获取连接的线程是否是同一个
boolean isSameThread = this.getOwnerThread() == Thread.currentThread();
if (!isSameThread) {
dataSource.setAsyncCloseConnectionEnable(true);
}
//不是同一个线程则执行syncClose进行关闭
if (dataSource.isAsyncCloseConnectionEnable()) {
//避免并发关闭需要先获得锁
syncClose();
return;
}
//通过AtomicIntegerFieldUpdater保证只有一个线程在执行关闭
if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {
return;
}
try {
for (ConnectionEventListener listener : holder.getConnectionEventListeners()) {
listener.connectionClosed(new ConnectionEvent(this));
}
//配置Filter,责任链执行后调用recycle方法
List<Filter> filters = dataSource.getProxyFilters();
if (filters.size() > 0) {
//执行责任链
FilterChainImpl filterChain = new FilterChainImpl(dataSource);
filterChain.dataSource_recycle(this);
} else {
recycle();
}
} finally {
CLOSING_UPDATER.set(this, 0);
}
this.disable = true;
}
public void syncClose() throws SQLException {
//需要先获得锁,再执行关闭
lock.lock();
try {
//已关闭||其他线程在执行关闭
if (this.disable || CLOSING_UPDATER.get(this) != 0) {
return;
}
//和close基本一致
...
this.disable = true;
} finally {
CLOSING_UPDATER.set(this, 0);
lock.unlock();
}
}
2、recycle
通过DruidAbstractDataSource.recycle 方法判断数据库连接进行的关闭还是归还到线程池内,以及是否需要创建新的连接。
protected void recycle(DruidPooledConnection pooledConnection) throws SQLException {
final DruidConnectionHolder holder = pooledConnection.holder;
//日志打印
if (holder == null) {
LOG.warn("connectionHolder is null");
return;
}
if (logDifferentThread
&& (!isAsyncCloseConnectionEnable())
&& pooledConnection.ownerThread != Thread.currentThread()) {
LOG.warn("get/close not same thread");
}
final Connection physicalConnection = holder.conn;
if (pooledConnection.traceEnable) {
Object oldInfo = null;
activeConnectionLock.lock();
try {
if (pooledConnection.traceEnable) {
oldInfo = activeConnections.remove(pooledConnection);
pooledConnection.traceEnable = false;
}
} finally {
activeConnectionLock.unlock();
}
if (oldInfo == null) {
if (LOG.isWarnEnabled()) {
LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size());
}
}
}
final boolean isAutoCommit = holder.underlyingAutoCommit;
final boolean isReadOnly = holder.underlyingReadOnly;
final boolean testOnReturn = this.testOnReturn;
try {
// 判断非自动提交的事务是否存在事务
if ((!isAutoCommit) && (!isReadOnly)) {
//执行回滚
pooledConnection.rollback();
}
//关闭连接的线程和获取连接的线程是否是同一个
boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread();
if (!isSameThread) {
final ReentrantLock lock = pooledConnection.lock;
lock.lock();
try {
//将连接信息重置
holder.reset();
} finally {
lock.unlock();
}
} else {
//将连接信息重置
holder.reset();
}
if (holder.discard) {
return;
}
//是否超过最大物理连接数
if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) {
//执行连接回收
discardConnection(holder);
return;
}
//判断连接是否已关闭
if (physicalConnection.isClosed()) {
lock.lock();
try {
if (holder.active) {
//活动线程数减1
activeCount--;
holder.active = false;
}
//关闭线程数加1
closeCount++;
} finally {
lock.unlock();
}
return;
}
//是否开启回收连接时候判断连接是否可用
if (testOnReturn) {
boolean validate = testConnectionInternal(holder, physicalConnection);
//连接不可用,调用close方法进行关闭
if (!validate) {
JdbcUtils.close(physicalConnection);
destroyCountUpdater.incrementAndGet(this);
lock.lock();
try {
if (holder.active) {
activeCount--;
//活动线程数减1
holder.active = false;
}
//关闭线程数加1
closeCount++;
} finally {
lock.unlock();
}
return;
}
}
if (holder.initSchema != null) {
holder.conn.setSchema(holder.initSchema);
holder.initSchema = null;
}
if (!enable) {
discardConnection(holder);
return;
}
boolean result;
final long currentTimeMillis = System.currentTimeMillis();
//是否超过最大物理连接时间
if (phyTimeoutMillis > 0) {
long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis;
if (phyConnectTimeMillis > phyTimeoutMillis) {
//执行连接回收 activeCount <= minIdle 执行连接的创建
discardConnection(holder);
return;
}
}
lock.lock();
try {
if (holder.active) {
activeCount--;
holder.active = false;
}
closeCount++;
//将连接PUT到连接池
result = putLast(holder, currentTimeMillis);
recycleCount++;
} finally {
lock.unlock();
}
//添加到连接池失败,执行连接关闭
if (!result) {
JdbcUtils.close(holder.conn);
LOG.info("connection recyle failed.");
}
} catch (Throwable e) {
holder.clearStatementCache();
if (!holder.discard) {
discardConnection(holder);
holder.discard = true;
}
LOG.error("recyle error", e);
recycleErrorCountUpdater.incrementAndGet(this);
}
}