I'm having problems with the connection pool in Tomcat after a database outage.
There's this heartbeat service servlet that won't come back up after a database outage.
I've already tried the standard answer, and beyond, specifically:
Adding to the Resource section in server.xml
validationQuery="select 1 from dual"
testOnBorrow="true"
removeAbandoned="true"
removeAbandonedTimeout="120"
logAbandoned="true"
Trying to close the connection with a check to validity:
if (connection != null && !connection.isValid(10)) {
connection.close();
}
(Resulted in java.sql.SQLException: Connection is closed)
Trying to abort the connection (not sure whether done right)
if (connection != null && !connection.isValid(10)) {
connection.abort();
}
(Resulted in java.lang.NoSuchMethodError: java.sql.Connection.abort(Ljava/util/concurrent/Executor;)V)
Tries 2) and 3) show that indeed the connection is invalid, and it knows it. The question is - how to destroy it?
Tomcat version: 7.0.29
The pool will destroy the invalid connection for you thanks to "testOnBorrow=true" setting (note that the "Abandoned" settings only apply to connections which are not returned to the pool).
So this is how it should go:
servlet borrows connection, does queries and returns connection to the pool.
servlet borrows connection, database crashes, servlet receives all kinds of horrible SQL errors but still returns connection to the pool.
database has restarted
on next heartbeat, servlet borrows connection. Tomcat's pool will "test on borrow", find that the old connection is broken, removes (and closes) connection, tries another, finds that it is also broken, etc, and THEN the pool decides to create a new connection, test it OK and hands it over to the servlet.
servlet receives new valid connection, does queries and returns connection to the pool.
I'm not sure how Tomcat's pool behaves when a "test on borrow" indicates a connection is broken (1): it might not create new connections right away or throw an error when it can't get a valid connection from the pool. But I expect the pool to effectively flush itself and re-populate with new (valid) connection.
(1) That is, if the "test on borrow" is actually done which this post indicates is not the case ...
If the pool does not flush itself, you can try to do this programmatically once you find connections are invalid. I have not tried this before, hopefully you can get it to work. Following method is described here:
Reach into the JNDI context, pull-out the DataSource object, cross your fingers, cast it to org.apache.tomcat.jdbc.pool.DataSource, and call the purge() method.
Alterntively, use JMX and call the purge method via the MBean.
If you experience hanging threads after a database crash, you might have to resort to a work around described in this answer.
If we want to dispose an ill java.sql.connection from Tomcat jdbc connection pool,
we may do this explicitly in the program.
Unwrap it into an org.apache.tomcat.jdbc.pool.PooledConnection, setDiscarded(true)
and close the JDBC connection finally, the ConnectionPool will remove the underlying connection once it has been returned.
(ConnectionPool.returnConnection(....))
PooledConnection pconn = conn.unwrap(PooledConnection.class);
pconn.setDiscarded(true);
conn.close();
Related
We are currently dealing with the function, that has to work partially with the database, and partially with a service, whice operations are time-consuming. So, generally speaking, here is a transactional method, that has a code like this:
Connection conn = null;
try {
conn = getConnection(); // This I get from the connection pool
Employee emp = queryDatabase(id);
// Point A - ??
Response resp = makeLongTimeServiceCall(emp);
// Point B - ??
anotherQueryDatabase(resp);
} catch (Exception e) {
throw e; // And this also rolls back the transaction
} finally {
// If conn is not closed, close it, so there would be no leaks
}
So the big question is - should I close the connection at point A and then get it again from the connection pool at point B, so that other servlets could use that connection while I interact with the service? My guess is that I should, but will this hurt my transaction?
In many circumstances: yes, closing and reopening the connection sounds good. However you need to understand the implication of doing them in two separate transactions (by closing and re-opening the connection you are inherently doing them in separate transaction).
If another user invokes an operation that changes the state of your data at Point B will the end result still be correct?
If you don't have a transaction you can close the connection and ask for a new connection when needed.
Remember that if you are using a connection pool closing a connection will not really close the connection, but only flag it as reusable by other threads.
Database connections shouldn't be left open. Open the connections just when you need to execute a query and close it as early as possible. So my solution is, YES.
if your application doesn't close connection properly may lead to some issues like the
connection pool maxing out.
Applications Not Properly Closing Connections:
When writing an application to use the WebSphere Application Server(WAS) datasource, the best way is fallowing get/use/close pattern.
1.get
-This is when the application makes a request to get a connection from the pool.
The application will first lookup the datasource name and then do a getConnection() call.
2.use
-This is when the application executes a query and waits for a response
3.close
-This is the final stage when the application has received the response from the database and is now done using that connection.
-The application should call close() in a finally block to close out the connection and return it to the free pool.
If your application does not follow this pattern, you may see connections staying open for long periods of time. This is especially seen when the application does not close the connection properly. After the response is received from the database, the application should be calling close in a finally block. If the application does not explicitly close the connection, that connection will stay open forever in WAS until that server is restarted. This is known as a connection leak. To resolve this type of issue, you will have to modify your application to close every connection
for further information: https://www.ibm.com/support/pages/common-reasons-why-connections-stay-open-long-period-time-websphere-application-server
I am using tomcat connection pooling. But I was following exception
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
So I put in the following lines in context.xml to find the leak :
removeAbandoned="true" logAbandoned="true" removeAbandonedTimeout="3"
Then I started getting following exception org.apache.tomcat.dbcp.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2015-01-17 22:12:18 by the following code was never closed:
So I found two culprit methods that were causing this leak. The two methods have common way of getting connection i.e. calling unwrap to get access to driver specific connection.
try (Connection conn = DataSourceConnectionPool.getConnection().unwrap(OracleConnection.class);
OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall(MIGRATE_ACCOUNT)) {
...
....
)
Important think to notice is that I am using try block from JDK7 i.e. Automatic Resource Management, so i dont need the finally block. Connection closing is handled by JDK automatically. But why this unwrapped connection is not closing. And when I am trying to do following :
try (Connection poolConn = DataSourceConnectionPool.getConnection();
Connection conn = poolConn.unwrap(OracleConnection.class);
I am getting java.sql.SQLException: Already closed. So how close this connection. Do I have to do it manually without using try block? Shouldn't try block handle be able to handle this?
This is incorrect usage of a connection pool. You should never call close() on an unwrapped connection.
The normal flow of using a pooled connection is
Get the Connection, the pool gets a physical connection and returns it wrapped in its own wrapper
You use the Connection
You call close() on the Connection. This doesn't actually close anything, the pool's wrapper intercepts the close() call and simply returns the (still active) connection to the pool.
This works because the pool has a wrapper class, say PoolableConnection that implements Connection. PoolableConnection delegates to the underlying connection for carrying out actual work, but it implements (amongst other things) close() differently. This destroys the current PoolableConnection wrapper and returns the underying Connection to the connection pool. For example.
This way, your program logic can get a connection from a DataSource, use the Connection and then close(), just as it would a normal, unpooled, Connection.
It's exactly this transparency that makes connection pools so easy to use.
Now, when you call unwrap, the PooledConnection gives you access to it's internal, real, Connection delegate.
What you do is call close() on the delegate!
This has two effects:
it does not call close() on PooledConnection, so the the Connection does not get returned to the pool.
it closes the underying connection from underneath the pool. This shouldn't be a problem, as the pool would deal with dropped connections itself.
So you need to be very careful. Always call close() on the Connection you have gotten from the pool, to return it to the pool. Never call close() on the underlying connection.
So your code should be:
try (final Connection poolConn = DataSourceConnectionPool.getConnection()) {
final Connection conn = poolConn.unwrap(OracleConnection.class);
//do stuff with conn
//do not close conn!!
}
//poolConn is returned to the pool
I run some tomcat application, use jndi connection pool.
In some time connection pool stops to give connections and application hangs.
Seems because some code receives connection and doesn't return it back to the pool.
How can I monitor - which code does it ?
More common - I want to see what all connections do at the moment.
I cannot change application. But I can adjust Tomcat, maybe add some interceptors.
Most connection pool implementations can be configured to detect connections that are not returned to the pool. E.g. for Tomcat's JDBC connection pool there are various configurations options for "abandoned connections" (connections for which the lease expired). If you search for "Abandoned" on this web-page, you'll find the options:
removeAbandoned
removeAbandonedTimeout
logAbandoned
suspectTimeout
As mentioned on the web-page, these settings will add a little overhead but at least your application will not hang. When testing your application, set a low value for removeAbandonedTimeout and a low value for maxActive so that you can catch unreturned connections early.
I never use the connection pool API itself, I always wrap it in a helper.
That way, I can do this in the helper:
private Exception created = (0 == 1) ? new Exception() : null;
When I run into problems like yours, I just change one character (0 -> 1) to have a stack trace of who created this instance in my debugger.
The database connection is get like below
public Connection getDBConection(){
Context context = new InitialContext();
DataSource dataSource = (javax.sql.DataSource) context.lookup("java:myDataSource");
Connection conn = dataSource.getConnection();
}
For a userA, is each database request should call getDBConnection() once; but no need to control all request use the same connection?
That is, if userA has three database request, then userA should call getDBConnection() three times, and call Connection.closed() after used in each request?
If the userA call getDBConnection() three times (that is, call dataSource.getConnection() three times), is three connection created? Or it is unknown and controlled by weblogic?
I feel very chaos, is it true that there should be one new connection for one database request? or just call DataSource.getConnection() for each database request and the number of new connection created is controlled by web server, no need to think how many connection is actually created.
Every time you call DataSource.getConnection, the data source will retrieve a connection for you. It should be true that the returned connection is not being actively used by anyone else, but it is not necessarily a brand-new connection.
For example, if you use a connection pool, which is a very common practice, then when you call Connection.close, the connection is not actually closed, but instead returns to a pool of available connections. Then, when you call DataSource.getConnection, the connection pool will see if it has any spare connections lying around that it hasn't already handed out. If so, it will typically test that they haven't gone stale (usually by executing a very quick query against a dummy table). If not, it will return the existing connection to the caller. But if the connection is stale, then the connection pool will retrieve a truly new connection from the underlying database driver, and return that instead.
Typically, connection pools have a maximum number of real connections that they will keep at any one time (say, 50). If your application tries to request more than 50 simultaneous connections, DataSource.getConnection will throw an exception. Or in some implementations, it will block for a while until one becomes available, and then throw an exception after that time expires. For a sample implementation, have a look at Apache Commons DBCP.
Hopefully that answers your question!
I'm new to c3op, and confused about the use of :
c3p0.idle_test_period
In this link : HowTo configure the C3P0 connection pool
idleTestPeriod : Must be set in hibernate.cfg.xml (or hibernate.properties), Hibernate default:
0, If this is a number greater than 0, c3p0 will test all idle, pooled but unchecked-out
connections, every this number of seconds.
What is the purpose of this kind of test (idel, pooled connections), and the relationship between c3p0.idle_test_period and c3p0.timeout?
The database server may close a connection on its side after a certain amount of time - causing some error in your application, because it'll attempt to send a query on a connection which is no longer available on the server side.
In order to avoid this you can let the pool periodically check a connection (Think of a ping) for it's validity. This is what idle_test_period is for.
timeout is the timespan after which the pool will remove a connection from the pool, because the connection wasn't checked out (used) for a while and the pool contains more connections than c3pO.min_size.
I think this setting is used in hibernate in order to validate pooled connection after every few seconds . Consider a scenario if on database side, password is changed. Hibernate already pooled connections on old password. So it is security breach having pool with wrong password.So when hibernate will validate after few seconds it . It will invalidate that pooled connection.