How best to close connections and avoid inactive sessions while using C3P0? - database

I am using c3p0 for my connection pooling. The ComboPooledDataSource I use is configured as below.
#Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("user");
dataSource.setDriverClass("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("test");
dataSource.setPassword("test");
dataSource.setMinPoolSize("10");
dataSource.setMaxPoolSize("20");
dataSource.setMaxStatements("100");
return dataSource;
}
I am facing some issues with this. I get warnings that this might leak connections. Also the below error from time to time,
as all the connections are being used up.
java.sql.SQLException: Io exception: Got minus one from a read call
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:439)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection
(WrapperConnectionPoolDataSource.java:182)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection
(WrapperConnectionPoolDataSource.java:171)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource
(C3P0PooledConnectionPool.java:137)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
And from the DB stat, could see almost 290 inactive connections. I am having around 8 applications deployed in two servers,
connecting to the same DB.
My queries are
How do I make sure th connections are closed and not to have these many inactive connections?
Would configuring idle time and timeout resolve this issue?
What would happen if the server is brought down/tomcat is shutdown, will the connections remain open?
Connections are mainly used during startup to load cache, so is there a way of not using these connections afterwards?
What should I do for the existing inactive connections?

Given maxPoolSize of 20 and eight deployments, you should expect to see up to 180 Connections, which may be inactive if the application has seen periods of traffic which has now subsided. You have configured nothing to encourage a fast scaling down of your pools -- set maxIdleTime and/or maxIdleTimeExcessConnections and/or maxConnectionAge.
You should probably tell Spring how to close the DataSource you've defined. Use #Bean(destroyMethodName="close") instead of #Bean alone above your dataSource() method.
You have not configured any sort of Connection testing, so even broken Connections might remain in the pool. Please see Simple Advice On Connection Testing.
If the issue were a Connection leak, clients would eventually hang indefinitely, as the pool would be out of Connections to check out, but would already have reached maxPoolSize, and so wouldn't be able to acquire more from the DBMS. Are you seeing clients hang like that?
The way you avoid Connection leaks is, post-Java7, to always acquire Connections from your DataSource via try-with-resources. That is, use...
try ( Connection conn = myDataSource.getConnection() ) {
...
}
rather than just calling getConnection() in a method that might throw an Exception or in a try block. If you are using an older version of Java, you need to use the robust resource cleanup idiom, that is, acquire the Connection in a try block and be sure that conn.close() is always closed in the finally block, regardless of any other failures in the finally block. If you are not working with the DataSource directly, but letting Spring utilities work with it, hopefully those utilities are doing the right thing. But you should post whatever warning you are receiving that warns you of potential Connection leaks!
If your application has little use for Connections after it has "warmed up", and you want to minimize the resource footprint, set minPoolSize to a very low number, and use maxIdleTime and/or maxIdleTimeExcessConnections and/or maxConnectionAge as above to ensure that the pool promptly scales down when Connections are no longer in demand. Alternatively you might close() the DataSource when you are done with its work, but you are probably leaving that to Spring.

Related

IIS 7 consuming connections and not releasing them

We have a asp.net website, hosted by IIS7. The website functions normally without any problem.
But after a while, like 1 or 2 months, the Sybase database which the website connects to will produce this error whenever accessed by any application : Maximum number of connections already opened
At first we didn't realize that it was the web site's application pool that causes this, so we restart the database and everything is back to normal.
But then the 2nd time, the 3rd time ... and we came to aware that we just need to restart the application pool for those unreleased connection to be released.
I checked the source code, there was only one place has database-connect-code and it was a very simple code which connects to the db, get the results then close it :
con.open()
x = con.getdata()
con.close
Btw, after checking the application's log, there wasn't any error or exceptions so I'm pretty sure that the con.close is probably reached and executed.
So if we could rule out the possibility that there were unclosed connections in the source code, is there any other explanation for this ?

List not disconnected or not properly disconnected Database-connections

I'm using a dynamic Java Web Application (Tomcat 8.0.15, Java EE 7 Web) with a SQL Server 2008 and after getting the warning/exception
WARNING [Tomcat JDBC Pool Cleaner[510210701:1481713957404]] org.apache.tomcat.jdbc.pool.ConnectionPool.suspect Connection has been marked suspect, possibly abandoned PooledConnection[net.sourceforge.jtds.jdbc.JtdsConnection#510fc080][67975 ms.]:java.lang.Exception
quite too often I wonder somewhere in the depths of my source code I forgot to disconnect a JDBC or Hibernate Connection to the database. I'd like to list them somehow.
A regular
static
{
try {
Context context = new InitialContext ();
dataSource = (DataSource) context.lookup("java:comp/env/jdbc/sqlserv");
} catch (NamingException ex) {
Logger.getLogger(Basisverbindung.class.getName()).log(Level.SEVERE, null, ex);
}
}
does that job and in my hibernate.cfg.xml it's the same:
<property name="hibernate.connection.datasource">java:comp/env/jdbc/sqlserv</property>
I looked through Stackoverflow and found only a few entries which I consulted already (and even upvoted):
Tomcat 7 connection pooling error
WebApp (Tomcat-jdbc) Pooled DB connection throwing abandon exception
https://dba.stackexchange.com/questions/114759/tomcat7-jdbc-connection-pool-connection-has-been-abandoned
But the issue persists or comes up again after a while so I would like to find a way how to track down where I forgot to close the connection. On my Tomcat there's also a PSI Probe running telling me there are coming up some errors in the requests and sometimes maxing out the Response time.
I see a nice list of requests there but don't know which ones are abandoned.
The ActivityMonitor in the SQL-Server Management Studio is not of too much help either it lists quite a few processes of which I know they are closed (or well, should be).
What's the best way to analyze that kind of problem?
What you really want to do is enable "abandoned connection" tracking and reporting.
You didn't say which of Tomcat's JDBC DataSource pools you were using (there are two), but they are configured similarly:
commons-dbcp2-based: logAbandoned=true, removeAbandonedOnBorrow=true
tomcat-jdbc-based: logAbandoned=true, removeAbandoned=true
I always recommend everyone run with a maximum pool size of 1 in development environments. This will help you identify pool leakage very quickly, plus catch any potential deadlocks you may have planted in your code.

Close SQL connections cleanly when connection dropped

Just wondering if there is a way that I can close all SQL connections and commands in the cleanest possible way when a connection is lost in VB.NET (can also be in C#.NET).
What I'm trying to achieve:
Using the System.Net.NetworkInformation.NetworkAvailabilityChanged event, I'm monitoring whether the connection has been lost. If it has been lost, I'm disabling all user input - works great. Network comes back on, UI is enabled. (thumbs up)
Now, however, comes my predicament. If an SQL query is executing before the connection drops and then the network is lost, then the query returns a null value as expected, however if that was mid population of datatables/fields, then I get NullReferenceExceptions.
My question is:
Is there anyway to cleanly exit a sub after the connection has dropped? I've tried Application.ExitThread, but that doesn't seem to quite cut it. Do I need to put dropped connection handlers within my objects, so that when the connection is dropped, the respective object won't return or try to assign null data?
Any help is greatly appreciated. Not asking for plain code, need explanations if at all possible. Cheers.
If you follow the "using" best practice, like:
Using cn As New SqlConnection(connectionString)
...
End Using
Then the compiler will generate code that cleans up the connection when an exception is thrown.

Entity framework, how to increase limits?

We are building an application which makes every week a very large amount of request over the database, concurrently.
We have ~15-20 threads which query the database concurrently.
We are actually encountering a lot of problems:
On the database side(not enough RAM): being resolved.
But on the client too. We have Exception when trying to get a connection or execute commands. Those commande are mades through entity framework.
The application has two part: one website and one console application.
So can anyone tell me how to increase the following values?
Connection Timeout
Command Timeout
Connection pool size
I think that there several things that have to be done on the server side(SQL Server or IIS), but I can't find where?
Command timeout can be set on ObjectContext instance. Connect timeout and connection pool size is configured in connection string but if you have only 15-20 threads your problem will most probably be somewhere else because default connection pool size is 100.
Enclose your objectContext in a using block so the context disposes after you have done your work.
you can make a method to pass in thread which uses your entity context to do the work you want and then dispose the connection after the work is finished, you can use the stateinfo object variable to pass in different parameters to use during the life of your method.
void DoContextWork(object stateInfo)
{
// wrap your context in a using clause
using(var objectContext = new YourEntity()
{
// Do work here
}
}
you can have multiple threads call this method and each time your connection gets called you can do your work on your DB without getting the issues you mentioned above.

Deadlocks causing 'Server failed to resume the transaction' with NHibernate and distributed transactions

We are having an issue when using NHibernate with distributed transactions.
Consider the following snippet:
//
// There is already an ambient distributed transaction
//
using(var scope = new TransactionScope()) {
using(var session = _sessionFactory.OpenSession())
using(session.BeginTransaction()) {
using(var cmd = new SqlCommand(_simpleUpdateQuery, (SqlConnection)session.Connection)) {
cmd.ExecuteNonQuery();
}
session.Save(new SomeEntity());
session.Transaction.Commit();
}
scope.Complete();
}
Sometimes, when the server is under extreme load, we'll see the following:
The query executed with cmd.ExecuteNonQuery is chosen as a deadlock victim (we can see it in SQL Profiler), but no exception is raised.
session.Save fails with the error message, "The operation is not valid for the state of the transaction."
Every time this code is executed after that, session.BeginTransaction fails. The first few times, the inner exception varies (sometimes it is the deadlock exception that should have been raised in step 1). Eventually it stabilizes to "The server failed to resume the transaction. Desc:3800000177." or "New request is not allowed to start because it should come with valid transaction descriptor."
If left alone, the application will eventually (after seconds or minutes) recover from this condition.
Why is the deadlock exception not being reported in step 1? And if we can't resolve that, then how can we prevent our application from temporarily becoming unusable?
The issue has been reproduced in the following environments
Windows 7 x64 and Windows Server 2003 x86
SQL Server 2005 and 2008
.NET 4.0 and 3.5
NHibernate 3.2, 3.1 and 2.1.2
I've created a test fixture which will sometimes reproduce the issue for us. It is available here: http://wikiupload.com/EWJIGAECG9SQDMZ
We've finally narrowed this down to a cause.
When opening a session, if there is an ambient distributed transaction, NHibernate attaches an event handler to the Transaction.TransactionCompleted, which closes the session when the distributed transaction is completed. This appears to be subject to a race condition wherein the connection may be closed and returned to the pool before the deadlock error propagates across, leaving the connection in an unusable state.
The following code will reproduce the error for us occasionally, even without any load on the server. If there is extreme load on the server, it becomes more consistent.
using(var scope = new TransactionScope()) {
//
// Force promotion to distributed transaction
//
TransactionInterop.GetTransmitterPropagationToken(Transaction.Current);
var connection = new SqlConnection(_connectionString);
connection.Open();
//
// Close the connection once the distributed transaction is
// completed.
//
Transaction.Current.TransactionCompleted +=
(sender, e) => connection.Close();
using(connection.BeginTransaction())
//
// Deadlocks but sometimes does not raise exception
//
ForceDeadlockOnConnection(connection);
scope.Complete();
}
//
// Subsequent attempts to open a connection with the same
// connection string will fail
//
We have not settled on a solution, but the following things will eliminate the problem (while possibly having other consequences):
Turning off connection pooling
Using NHibernate's AdoNetTransactionFactory instead of AdoNetWithDistributedTransactionFactory
Adding error handling that calls SqlConnection.ClearPool() when the "server failed to resume the transaction" error occurs
According to Microsoft (https://connect.microsoft.com/VisualStudio/feedback/details/722659/), the SqlConnection class is not thread-safe, and that includes closing the connection on a separate thread. Based on this response we have filed a bug report for NHibernate (http://nhibernate.jira.com/browse/NH-3023).
not a definitive answer, but i suspect you have some problems with session management and that you are using the same session across multiple calls to handlers. i don't think it's actually the connection that is in a bad state, but rather the nhibernate session. this doesn't seem to jive with you not seeing the problem with connection pooling turned off, so i may be off base, but i still suspect it has to do with reusing sessions.
the first thing i would suggest is that you try to confirm this by logging the hashcode of the session and the hashcode of session.GetSessionImplementation() (my understanding of using the castle nhibernate facility is that you will see the same instance of session, even though it is actually a different session and the session implementation will actually show a difference). see if you are seeing the same hashcodes being used in handling different messages.
if it is a question of session management, try using a nservicebus module to manage your sessions for your handlers. here is a post from andreas about doing that. i don't think his edit about having a way to do this built in on the trunk was in the 2.5 release, so you probably want to go ahead with this. (i could be wrong about that.)
http://andreasohlund.net/2010/02/03/nhibernate-session-management-in-nservicebus/
This doesn't exactly solve your problem, but you could make your IPreInsertEventListener just send a NSB message, and then have the receiver of the message invoke the stored procedure. I've done that with problematic pre-and post event listeners while using NHibernate and NSB in the past.
Another thought is have your pre-event listener create its own connection object wrapped in a nice using statement, then it won't touch NHibernate's connection. If it deadlocks, then just do a throw an make sure you've disposed of any object's in scope.
It is an NHibernate issue. NHibernate is not opening and closing the connection on the same thread, which is not supported by ADO.NET. You can work around it by opening and closing the connection yourself. NHibernate will not close the connection unless it has also opened it.
Workaround
var connection = ((SessionFactoryImpl)_sessionFactory).ConnectionProvider.GetConnection();
using(var session = _sessionFactory.OpenSession(connection))
{
//do database stuff
}
connection.Close();

Resources