views:

1642

answers:

6

The last few days we see this error message in our website too much:

"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."

We have not changed anything in our code in a while. I revised the code to check open connections which didn't close, but found everything to be fine.

  • How can I solve this?

  • Do I need to edit this pool?

  • How can I edit this pool's max number of connections?

  • What is the recommended value for a high traffic website?


Update:

Do I need to edit something in IIS?

Update:

I found that the number of active connections are anywhere from 15 to 31, and I found that the max allowed number of connections configured in SQL server is more than 3200 connections, is 31 too many or should I edit something in the ASP.NET configration?

+1  A: 

You can specify minimum and maximum pool size by specifying MinPoolSize=xyz and/or MaxPoolSize=xyz in the connection string. This cause of the problem could be a different thing however.

Mehrdad Afshari
Whats the recommended MaxPoolSize?
Amr ElGarhy
Probably, the best way to go is *not* to specify it unless you have special requirements and you know a good pool size for your *specific case*.
Mehrdad Afshari
Note: i checked and i found that the active connections to my db are around 22 live one, is that too much?
Amr ElGarhy
I don't think so. The default pool size is 100 connections I think. It depends on the load of each connection on the network and SQL server. If those are running heavy queries, it might cause problems. Also, network issues might occur when *initiating* a new connection and may cause that exception.
Mehrdad Afshari
+3  A: 

Unless your usage went up a lot, it seems unlikely that there is just a backlog of work. IMO, the most likely option is that something is using connections and not releasing them promptly. Are you sure you are using using in all cases? Or (through whatever mechanism) releasing the connections?

Marc Gravell
+3  A: 

Did you check for DataReaders that are not closed and response.redirects before closing the connection or a datareader. Connections stay open when you dont close them before a redirect.

Ivo
+1 - Or functions returning DataReaders - Connection will never close outside the function you created them...
splattne
+1  A: 

I have encountered this problem too, when using some 3rd party data layer in one of my .NET applications. The problem was that the layer did not close the connections properly.

We threw out the layer and created one ourselves, which always closes and disposes the connections. Since then we don't get the error anymore.

Wim Haanstra
We are using LLBL and the website is running from 2 years and just the last few days started to act like this.
Amr ElGarhy
+7  A: 

In most cases connection pooling problems are related to "connection leaks." Your application probably doesn't close its database connections correctly and consistently. When you leave connections open, they remain blocked until the .NET garbage collector closes them for you by calling their Finalize() method.

You want to make sure that you are really closing the connection. For example the following code will cause a connection leak, if the code between .Open and Close throws an exception:

SqlConnection myConnection = new SqlConnection(ConnectionString);
myConnection.Open();
// some code
myConnection.Close();                

The correct way would be this:

SqlConnection myConnection = new SqlConnection(ConnectionString);
try
{
     conn.Open();
     someCall (myConnection);
}
finally
{
     myConnection.Close();                
}

or

using (SqlConnection myConnection = new SqlConnection(ConnectionString))
{
     myConnection.Open();
     someCall(myConnection);
}

When your function returns a connection from a class method make sure you cache it locally and call its Close method. You'll leak a connection using this code for example:

OleDbCommand myCommand new OleDbCommand(SomeUpdateQuery, getConnection());
result = myCommand.ExecuteNonQuery();
myConnection().Close(); 

The connection returned from the first call to getConnection() is not being closed. Instead of closing your connection, this line creates a new one and tries to close it.

If you use SqlDataReader or a OleDbDataReader, close them. Even though closing the connection itself seems to do the trick, put in the extra effort to close your data reader objects explicitly when you use them.


This article "Why Does a Connection Pool Overflow?" from MSDN/SQL Magazine explains a lot of details and suggests some debugging strategies:

  • Run sp_who or sp_who2. These system stored procedures return information from the sysprocesses system table that shows the status of and information about all working processes. Generally, you'll see one server process ID (SPID) per connection. If you named your connection by using the Application Name argument in the connection string, your working connections will be easy to find.
  • Use SQL Server Profiler with the SQLProfiler TSQL_Replay template to trace open connections. If you're familiar with Profiler, this method is easier than polling by using sp_who.
  • Use the Performance Monitor to monitor the pools and connections. I discuss this method in a moment.
  • Monitor performance counters in code. You can monitor the health of your connection pool and the number of established connections by using routines to extract the counters or by using the new .NET PerformanceCounter controls.
splattne
A small correction: the GC never calls an object's Dispose method, only its finalizer (if there is one). The finalizer can then do a "fallback" call to Dispose, if necessary, although I'm not certain whether SqlConnection does so.
LukeH
Right, edited the answer.
splattne
+1  A: 

We encounter this problem from time to time on our web site as well. The culprit in our case, is our stats/indexes getting out of date. This causes a previously fast running query to (eventually) become slow and time out.

Try updating statistics and/or rebuilding the indexes on the tables affected by the query and see if that helps.

Alex Czarto