Running batch updates on a very low-configuration machine today~~~
Running for about 30 minutes ~~This configuration ~~This program~~~
And then the magnificent newspaper went off the beaten track.~~~
This is the specific exception.
DEBUG: (BaseJdbcLogger.java:132) ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@4d4e22e1] [2014-07-17 15:19:35]5363945354 [Druid-ConnectionPool-Destory-1422598563] com.alibaba.druid.pool.DruidDataSource:1132 WARN : (DruidDataSource.java:1132) get/close not same thread ERROR: (DruidDataSource.java:1815) abandon connection, open stackTrace at java.lang.Thread.getStackTrace(Thread.java:1588) at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:942) at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4534) at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:661) at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4530) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:880) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)
This is the initial anomaly, followed by One big Batch exception
Caused by: java.sql.SQLException: connection holder is null at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1085) at com.alibaba.druid.pool.DruidPooledConnection.getMetaData(DruidPooledConnection.java:825) at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:285) ... 70 more
Say holder is empty
The first sight of holder is like the source code to Spring, which is full of holders (laughter).
But the holder here is not in Spirng, it's Druid.
This holder is probably used to hou the connection in the connection pool.
Then why is it empty? Visually, which link is broken or unexpectedly shut down ____________
According to the abnormal source code at com.alibaba.druid.pool.DruidDataSource.getConnection Direct (DruidDataSource.java:942)
if (isRemoveAbandoned()) { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); poolalbeConnection.setConnectStackTrace(stackTrace); poolalbeConnection.setConnectedTimeNano(); poolalbeConnection.setTraceEnable(true); synchronized (activeConnections) { activeConnections.put(poolalbeConnection, PRESENT); } }
You can't see anything. You can only keep looking at the log, or you can't see anything.
After looking at the above code several times, I always feel that isRemoveAbandoned() is a ghost method.
Look at the caller.
Well, this Destroy Connection Thread is very suspicious, jump.
if (isRemoveAbandoned()) { removeAbandoned(); }
public int removeAbandoned() { int removeCount = 0; long currrentNanos = System.nanoTime(); List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>(); synchronized (activeConnections) { Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator(); for (; iter.hasNext();) { DruidPooledConnection pooledConnection = iter.next(); if (pooledConnection.isRunning()) { continue; } long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000); if (timeMillis >= removeAbandonedTimeoutMillis) { iter.remove(); pooledConnection.setTraceEnable(false); abandonedList.add(pooledConnection); } } } ....slightly }
Erase, it's not right here, = removeAbandoned Timeout Millis timeMillis This is the time when getConnection() was called.
It means that after a connection is got, I'll kill you for so long after it's over removeAbandoned Timeout Millis.
Then continue looking for removeAbandoned Timeout Millis where it was set up, and finally find out that
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="1800" />
The initialization configuration is set here, and the two parameters roughly mean that,
Connections made through datasource.getConnontion() must call close() within so many seconds of removeAbandonedTimeout, or I'll kill you. (That is, conn can't exceed the specified lease period)
Then set it to two hours.~~~
Then the program successfully ran through ~~gorgeous wait for 50 minutes
Summary:
In order to prevent the program from forgetting to return the connection from the pool, connection pool provides some parameters to set a lease period, which can prevent connection leakage to some extent.
But if your business really needs to run for so long, pay attention to this setup.