diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index c282ed9e13..00e653b63e 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -271,6 +271,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat */ protected void recycle(PoolableConnection pooledConnection) throws SQLException { final Connection conn = pooledConnection.getConnection(); + ConnectionHolder holder = pooledConnection.getConnectionHolder(); + + assert holder != null; + try { if (activeConnectionTraceEnable) { activeConnections.remove(pooledConnection); @@ -280,6 +284,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (conn == null || conn.isClosed()) { lock.lock(); try { + holder.reset(); decrementActiveCount(); closeCount++; } finally { @@ -306,6 +311,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (count >= maxIdle) { lock.lock(); try { + holder.reset(); conn.close(); decrementActiveCount(); } finally { @@ -328,7 +334,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat closeCount++; // 第六步,加入队列中(putLast) - putLast(pooledConnection.getConnectionHolder()); + holder.reset(); + putLast(holder); recycleCount++; } finally { lock.unlock(); diff --git a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java index 5e0856186b..08abef32f9 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java @@ -57,7 +57,7 @@ public class PoolableConnection implements PooledConnection, Connection { protected SQLException handleException(Throwable t) throws SQLException { final ConnectionHolder holder = this.holder; - // + // if (holder != null) { DruidAbstractDataSource dataSource = holder.getDataSource(); if (dataSource != null) { @@ -124,7 +124,6 @@ public class PoolableConnection implements PooledConnection, Connection { } holder.getDataSource().recycle(this); - holder.reset(); holder = null; conn = null; } diff --git a/src/main/java/com/alibaba/druid/pool/PoolableStatement.java b/src/main/java/com/alibaba/druid/pool/PoolableStatement.java index 49125db5c2..60f0f4d956 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableStatement.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableStatement.java @@ -31,6 +31,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { private final Statement stmt; protected PoolableConnection conn; protected final List resultSetTrace = new ArrayList(); + protected boolean closed = false; public PoolableStatement(PoolableConnection conn, Statement stmt){ this.conn = conn; @@ -49,6 +50,10 @@ public class PoolableStatement extends PoolableWrapper implements Statement { this.conn = conn; } + public Statement getStatement() { + return stmt; + } + protected void clearResultSet() { for (ResultSet rs : resultSetTrace) { try { @@ -90,6 +95,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { clearResultSet(); stmt.close(); + this.closed = true; conn.getConnectionHolder().removeTrace(this); } @@ -409,6 +415,10 @@ public class PoolableStatement extends PoolableWrapper implements Statement { @Override public final boolean isClosed() throws SQLException { + if (this.closed) { + return true; + } + try { return stmt.isClosed(); } catch (Throwable t) { diff --git a/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest.java b/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest.java index deb69d92ad..3fd5510165 100644 --- a/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest.java @@ -19,7 +19,7 @@ public class StatFilterTest extends TestCase { public void setUp() throws Exception { JdbcStatManager.getInstance().reset(); } - + public void tearDown() throws Exception { JdbcStatManager.getInstance().reset(); } @@ -27,7 +27,7 @@ public class StatFilterTest extends TestCase { public void test_stat() throws Exception { String url = "jdbc:wrap-jdbc:filters=default:jdbc:mock:xx"; Connection conn = DriverManager.getConnection(url); - + Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT 1"); while (rs.next()) { @@ -35,18 +35,22 @@ public class StatFilterTest extends TestCase { } rs.close(); stmt.close(); - + conn.close(); - + TabularData sqlList = JdbcStatManager.getInstance().getSqlList(); Assert.assertEquals(true, sqlList.size() > 0); - + + int count = 0; for (Object item : sqlList.values()) { CompositeData row = (CompositeData) item; - Assert.assertEquals(url, (String) row.get("URL")); + if (url.equals((String) row.get("URL"))) { + count++; + } Assert.assertEquals(0, row.get("Count_50000_more")); } - + Assert.assertEquals(true, count > 0); + System.out.println(JSON.toJSONString(sqlList)); } } diff --git a/src/test/java/com/alibaba/druid/pool/benckmark/Oracle_Case3.java b/src/test/java/com/alibaba/druid/pool/benckmark/Oracle_Case3.java new file mode 100644 index 0000000000..be61ef843b --- /dev/null +++ b/src/test/java/com/alibaba/druid/pool/benckmark/Oracle_Case3.java @@ -0,0 +1,122 @@ +package com.alibaba.druid.pool.benckmark; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import java.text.NumberFormat; +import java.util.concurrent.CountDownLatch; + +import javax.sql.DataSource; + +import junit.framework.TestCase; + +import org.apache.commons.dbcp.BasicDataSource; + +import com.alibaba.druid.TestUtil; +import com.alibaba.druid.pool.DruidDataSource; + +public class Oracle_Case3 extends TestCase { + + private String jdbcUrl; + private String user; + private String password; + private String driverClass; + private int maxIdle = 40; + private int maxActive = 50; + private int maxWait = 5000; + private String validationQuery = "SELECT 1 FROM DUAL"; + private int threadCount = 14; + private int loopCount = 3; + final int LOOP_COUNT = 100 * 1; + private boolean testOnBorrow = true; + + protected void setUp() throws Exception { + jdbcUrl = "jdbc:oracle:thin:@10.20.149.85:1521:ocnauto"; + user = "alibaba"; + password = "ccbuauto"; + driverClass = "oracle.jdbc.driver.OracleDriver"; + } + + public void test_0() throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + + dataSource.setMaxActive(maxActive); + dataSource.setMaxIdle(maxIdle); + dataSource.setMaxWait(maxWait); + dataSource.setPoolPreparedStatements(true); + dataSource.setDriverClassName(driverClass); + dataSource.setUrl(jdbcUrl); + dataSource.setPoolPreparedStatements(true); + dataSource.setUsername(user); + dataSource.setPassword(password); + dataSource.setValidationQuery(validationQuery); + dataSource.setTestOnBorrow(testOnBorrow); + + for (int i = 0; i < loopCount; ++i) { + p0(dataSource, "druid", threadCount); + } + System.out.println(); + } + + public void test_1() throws Exception { + final BasicDataSource dataSource = new BasicDataSource(); + + dataSource.setMaxActive(maxActive); + dataSource.setMaxIdle(maxIdle); + dataSource.setMaxWait(maxWait); + dataSource.setPoolPreparedStatements(true); + dataSource.setDriverClassName(driverClass); + dataSource.setUrl(jdbcUrl); + dataSource.setPoolPreparedStatements(true); + dataSource.setUsername(user); + dataSource.setPassword(password); + dataSource.setValidationQuery(validationQuery); + dataSource.setTestOnBorrow(testOnBorrow); + + for (int i = 0; i < loopCount; ++i) { + p0(dataSource, "dbcp", threadCount); + } + System.out.println(); + } + + private void p0(final DataSource dataSource, String name, int threadCount) throws Exception { + + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch endLatch = new CountDownLatch(1); + for (int i = 0; i < threadCount; ++i) { + Thread thread = new Thread() { + + public void run() { + try { + startLatch.await(); + + for (int i = 0; i < LOOP_COUNT; ++i) { + Connection conn = dataSource.getConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT 1 FROM DUAL"); + rs.next(); + rs.close(); + stmt.close(); + conn.close(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + endLatch.countDown(); + } + }; + thread.start(); + } + long startMillis = System.currentTimeMillis(); + long startYGC = TestUtil.getYoungGC(); + long startFullGC = TestUtil.getFullGC(); + startLatch.countDown(); + endLatch.await(); + + long millis = System.currentTimeMillis() - startMillis; + long ygc = TestUtil.getYoungGC() - startYGC; + long fullGC = TestUtil.getFullGC() - startFullGC; + + System.out.println("thread " + threadCount + " " + name + " millis : " + NumberFormat.getInstance().format(millis) + ", YGC " + ygc + " FGC " + fullGC); + } +}