Connection pool issues on shared hosting with proper disposal - c#

I know that there is a similar question like this on Stack Overflow, but it doesn't quite fit what I have tried. I believe the reason for this problem is different, although the end-result is the same.
Whenever my site has been running for about two or three days, I get the following error (which is obviously caused by either connections/queries hanging, or not being disposed properly).
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
At first, I did some investigation and realized that using using, using a finalize call and other solutions weren't enough. The error would still eventually occur.
So I decided to figure out wether or not the Server Explorer (which I use often) in Visual Studio leaks connections. I had already changed the maximum execution and connection timeout to 3 seconds, and had reduced the pool size to 10 connections, so the Server Explorer could be the cause. No luck!
So what do I try now?

Here's the code I solved the problem with. When connecting, catch the exception and clear all pools, and then try again.
_connection =
new SqlConnection(connectionString);
try
{
_connection.Open();
}
catch (InvalidOperationException)
{
SqlConnection.ClearAllPools();
_connection.Open();
}
Also, when disposing the connection, make sure to clear the pools.
if (_connection != null)
{
SqlConnection.ClearAllPools();
_connection.Close();
_connection.Dispose();
}

Related

Proper way to open and close connection in loop

I have a code like below :
public void Do
{
using (var myConnection = new SqlConnection(connectionString))
{
for (int i = 0; i < 4; i++)
{
MyProcess.Execute(myConnection);
}
myConnection.Close();
myConnection.dispose();
}
}
public class MyProcess
{
public void Execute(SqlConnection myConnection)
{
if (myConnection.State == ConnectionState.Closed)
myConnection.Open();
//long running code
}
}
Execute methods sometimes take 5-10 minutes,sometimes run in 1-2 minutes for each iteration.
Now here i am confused that whether i shall open and close connection for each iteration and this will be efficient or whether i open and close connection 1 time only.
But with opening and closing connection once, this will hold resource for each of the iteration and will consume resource.
So i am not getting what should be the proper way to handle this
Can anybody please give me some advice on this?
ADO.NET uses Connection Pooling under the hood. That is why opening a new connection each time should not be an issue. Your call to myConnection.Open() will not actually result in opening of physical connection to the Database each time.
Check also this question. It's author made a measure test for connection opening. I have shown him that time of subsequent calls to DbConnection.Open() approaches to 0.
The most preferred way of using DbConnection is to open it for the minimal time period. If your MyProcess.Execute() has a lot of other non-DB related logic that takes considerable time, you should not keep an opened connection during this execution.
Check also Best Practices for Using ADO.NET article. It has following explicit statement:
High performance applications keep connections to the data source in
use for a minimal amount of time, as well as take advantage of
performance enhancing technology such as connection pooling.
So when does Ado.net removes the connection from connection pool?
This article provides some internal details on connection pooling:
The connection pooler removes a connection from the pool after it has
been idle for approximately 4-8 minutes, or if the pooler detects that
the connection with the server has been severed. Note that a severed
connection can be detected only after attempting to communicate with
the server. If a connection is found that is no longer connected to
the server, it is marked as invalid. Invalid connections are removed
from the connection pool only when they are closed or reclaimed.
This article also provides some details on pooling tuning if it's required. However you should consider such manual configuration only if you experience some performance issues caused by the pooling.

C# SqlConnections using up entire connection pool

I've written a service that occasionally has to poll a database very often. Usually I'd create a new SqlConnection with the SqlDataAdapter and fire away like this:
var table = new DataTable();
using(var connection = new SqlConnection(connectionString))
{
connection.Open();
using(var adapter = new SqlDataAdapter(selectStatement, connection))
{
adapter.Fill(table);
}
}
However in a heavy load situation (which occurs maybe once a week), the service might actually use up the entire connection pool and the service records the following exception.
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Multiple threads in the service have to access the SQL server for various queries and I'd like as much of them to run in parallel as possible (and that obviously works too well sometimes).
I thought about several possible solutions:
I thought about increasing the connection pool size, however that might just delay the problem.
Then I thought about using a single connection for the service and keep that open for the remainder of the service running, which might a simple option, however it will keep the connection open even if there is no workload to be done and would have to handle connection resets by the server etc. which I do not know the effect of.
Lastly I thought about implementing my own kind of pool that manages the number of concurrent connections and keeps the threads on hold until there is a free slot.
What would be the recommended procedure or is there a best practice way of handling this?
Well the solution in the end was not exactly ideal (fixing the issue on the SQL Server side) so I ended up checking the number of concurrent connections in the job queuing system.
The service will now not create another thread for document generation unless it can guarantee that the connection pool is actually available. The bad bottleneck on the SQL server is still in place, however the service now no longer generates exceptions.
The downside of course is, that the queue gets longer while there is some blocking query executing on the SQL Server, which might delay document generation for a minute or two. So it isn't an ideal solution but a workable one, since the delay isn't critical as the documents aren't needed directly but stored for archival purpose.
The better solution would have been to fix it SQL Server side.

What can cause a timeout getting SQL connection from pool?

I have a web app deployed under IIS. It's been getting timeout errors, and I believe I've tracked the problem down to code that doesn't properly dispose of SQL connections.
This will require quite a lot of surgery to fix, so at least until I can finish implementing and testing the new code, using using blocks correctly, I decided to bump up the connection pool size to something astronomical. But that doesn't seem to have helped. My connection string is:
Data Source=MyServer;Initial Catalog=MyDb;User ID=MyUser;Password=MyPwd;Max Pool Size=10000
And my log file shows:
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
I have been keeping Performance Monitor open over this period, and the number of user connections maxed out at around 150. So I don't think it can be that we're running out of connections.
What else could be causing this error?
Unfortunately SqlCommand does not obey ConnectionString or SqlConnection's time-out. And it has to be set manually. It's because the time-out mentioned in connection string is used for connecting, not executing. So that please consider setting up it's time-out by code.
var conn = new SqlConnection(cs);
var cmd = conn.CreateCommand();
cmd.CommandTimeout = conn.ConnectionTimeout;
...

When we can use ClearAllPools method?

I face the following problem :
Connection Pool has reached the maximum number of connections
I followed all the recommendations. the problem is n't like before but it happens rarely !!
I use the Using statement with all my connections and Readers .
Lately i face the following error , and i had to reset the iis to fix my problem.
Connection Pool has reached the maximum number of connections. at IBM.Data.Informix.IfxConnectionPool.ReportOpenTimeOut()
at IBM.Data.Informix.IfxConnectionPool.Open(IfxConnection connection)
at IBM.Data.Informix.IfxConnPoolManager.Open(IfxConnection connection)
at IBM.Data.Informix.IfxConnection.Open()
at DB_Connection_s.DB_Connection.GetUserSystems(String emp_num)
Now I read about this method ClearAllPools() .but i don't know when to use this method .and if this considered as a good solution to prevent the have to reset the iis to fix the request time out problem ??
You can call ClearAllPools() when you dont have any active connection.
also check out http://www.codeproject.com/Articles/46267/Connection-Pooling-in-ASP-NET
Ensure that your application closes all database connections correctly and consistently.
Ensure that the database is online.
Increase the connection timeout.
The error pattern indicates that connections are "leaked" over a long period. To fix this problem, ensure that your application closes all database connections correctly and consistently.
The exception does not indicate that the database is offline. The exception indicates a connection pool problem.

ASP.NET SqlConnection Timeout issue

I have run into a frustrating issue which I originally thought was a connection leak but that does not seem to be the case. The secnario is this: the data access for this application is using the Enterprise Libraries (v4) from Microsoft. All data access calls are wrapped in using statements such as
using (DbCommand dbCommand = db.GetStoredProcCommand("sproc"))
{
db.AddInParameter(dbCommand, "MaxReturn", DbType.Int32, MaxReturn);
...more code
}
Now the index of this application makes 8 calls to the database to load everything and I can bring the application to its knees by refreshing the index about 15 times. It seems that when the the database reaches 113 connections is when I recieve this error. Here is what makes this weird:
I have run similar code with the entlib on high traffic sites and have NEVER had this problem ever.
If I kill all the connections to the database and get the production application back up and running everytime I refresh the application I can run this SQL
SELECT DB_NAME(dbid) as 'Database Name',
COUNT(dbid) as 'Total Connections'
FROM sys.sysprocesses WITH (nolock)
WHERE dbid > 0
GROUP BY dbid
I can see the number of connections actively increasing with each page refresh. Running the same code on my local box with the same connection string does not cause this problem. Further if the production website is down I can fire up the site via Visual Studio and run it fine and the only difference between the two is that the production site has Windows authentication turned on and my local copy doesn't. Turning windows authentication off seems to have no effect on the server.
I have absolutely no clue what is causing this or why the connections are not being disposed of in SQL Server. The EntLib objects do no explose .Close() methods for anything so I can't explictily close the object.
Any thoughts?
Thanks!
Edit
Wow I just noticed that I never actually posted the error message. Oy. The actual connection error is: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Check that the stored procedure you are executing is not running into a row or table lock. Also if you can possibly try to deploy in another server and check if the application would crawl again.
Also try to increase the maximum allowed connections for your SQL server.
think the “Timeout Expired” error is a general issue and may have seveal causes. Increasing the TimeOut can solve some of them but not all.
You may also refer to the following links to troubleshoot and fix the error
http://techielion.blogspot.com/2007/01/error-timeout-expired-timeout-period.html
Could it be a configuration issue on the server?
How do you make a connection to the database on the production server?
That might be an area worth looking into.
While I don't know the answer I can suggest that for some reason connections are not being closed by you application when run in production. (Stating the obvious)
You might want examine your network configuration between the web server and sql server. High latency networks can cause connections not being closed in time.
Also it might help looking at the performance counters listed in the end of the following msdn article:
http://msdn.microsoft.com/en-us/library/8xx3tyca%28VS.71%29.aspx
Finally, if nothing else helps, I'd get debugger and Enterprise Library source code on production and debug your code inside the enterprise library to find out why connections are not being closed.
Silly question are you properly closing your DataReader? If not this could be the problem and the difference in behaviour between dev and prod can be caused by different garbage collection patterns.
I would disable connection pooling and try to suppress it (heh). Just add ";Pooling=false" to your connection string.
Or, perhaps you could add something like the following 'cleanup' code to your page (which closes any connection left open when the page unloads) - right in the 'using' clause:
System.Web.UI.Page page = HttpContext.Current.Handler as System.Web.UI.Page;
if (page != null) {
page.Unload += (EventHandler)delegate(object s, EventArgs e) {
try {
dbCommand.Connection.Close();
} catch (Exception) {
} finally {
result = null;
}
};
}
Also, make sure you've enabled the 'shared memory' protocoll if your SQL server and IIS are on the same machine (a real performance booster)!

Categories

Resources