Professional Documents
Culture Documents
• Connect Timeout - controls the wait period in seconds when a new connection is
requested, if this timeout expires, an exception will be thrown. Default is 15
seconds.
• Max Pool Size - specifies the maximum size of your connection pool. Default is
100. Most Web sites
do not use more than 40 connections under the heaviest load but it depends on
how long your database operations take to complete.
• Min Pool Size - initial number of connections that will be added to the pool upon
its creation. Default is zero; however, you may chose to set this to a small number
such as 5 if your application needs consistent response times even after it was idle
for hours. In this case the first user requests won't have to wait for those database
connections to establish.
• Pooling - controls if your connection pooling on or off. Default as you may've
guessed is true. Read on to see when you may use Pooling=false setting.
at
System.Data.SqlClient.SqlConnectionPoolManager.GetPooledConnection(SqlConnectionString
options, Boolean& isInTransaction)
at System.Data.SqlClient.SqlConnection.Open()
When you intend to close your database connection, you want to make sure that you are
really closing it. The following code looks fine yet causes a connection leak:
conn.Open();
doSomething();
conn.Close();
If doSomething() throws an exception - conn will never get explicitly closed. Here is how
this can be corrected:
try
{
conn.Open();
doSomething(conn);
finally
conn.Close();
or
conn.Open();
doSomething(conn);
Did you notice that in the first example we called conn.Close() explicitly while in the
second one we make the compiler generate an (implicit) call to conn.Dispose()
immediately following the using block? The C# using block guarantees that the Dispose
method is called on the subject of the using clause immediately after the block ends.
Close and Dispose methods of Connection object are equivalent. Neither one gives you
any specific advantages over the other.
When returning a connection from a class method - make sure you cache it locally and
call its Close method. The following code will leak a connection:
intres = cmd.ExecuteNonQuery();
If you use SqlDataReader, OleDbDataReader, etc., 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.
Last but not the least, never Close or Dispose your connection or any other managed
object in the class destructor or your Finalize method. This not only has no value in
closing your connections but also interferes with the garbage collector and may cause
errors. For more information see http://msdn.microsoft.com/library/en-
us/cpguide/html/cpconprogrammingessentialsforgarbagecollection.asp.
The only way to know the effect of your changes on connection pooling behavior is to
load-test your application. If you have existing unit tests - use them. Running your unit
tests repeatedly in a loop may create a fair bit of stress on application. If you don't, use
the Web load testing tool. There are plenty of commercial load testing tools on the market.
If you prefer freeware, consider OpenSTA available at www.opensta.org. All you need to
setup your load test is to install the tool, bring up your Web application and click your
way through. OpenSTA will record your HTTP requests into test scenarios that you can
run as part of your load test.
Knowing that your application crashes under the load doesn't often help to locate the
problem. If the app crashes fairly quickly, all you may need to do is run several load tests
- one for each module and see which one has a problem. However, if it takes hours to
crash you will have to take a closer look.
Most of the time you just need to know if your application manages to stay within the
size of its connection pool. If the load doesn't change, but the number of connections
constantly creep even after the initial "warm-up" period, you are most likely dealing with
a connection leak. The easiest way to monitor the number of database connections is by
using the Performance Monitor available under Administrative tools on most Windows
installations. If you are running SQL Server, add SQL Server General Statistics -> User
Connections performance counter (The counter is available on the SQL Server machine
so you may need to put its name or IP address into the Select Counters From Computer
box). The other way to monitor the number of database connections is by querying your
DBMS. For example, on SQL Server run:
EXEC SP_WHO
Or on Oracle, run:
SELECT * FROM V$SESSION WHERE PROGRAM IS NOT NULL
In documentation you may run into .Net CLR Data performance counters. They are great
if you know what they can and cannot do. Keep in mind that they do not always reset
properly. The following KB article sheds some light on the problem but in my opinion
does not cover all the issues: http://support.microsoft.com/default.aspx?scid=kb;en-
us;314429. Another thing to keep in mind is that IIS unloads app domains under stress so
don't be surprised when your number of database connections has dropped to zero while
your min pool size is five!
What if you discovered the connection pooling issue in production and you cannot take it
offline to troubleshoot? Turn pooling off. Even though your app will take a performance
hit, it shouldn't crash! Your memory footprint will also grow. What if it doesn't crash all
that often, and you don't want to take a performance hit? Try this:
try
conn.ConnectionString = "integrated
security=SSPI;SERVER=YOUR_SERVER;DATABASE=YOUR_DB_NAME;Min
Pool Size=5;Max Pool Size=60;Connect Timeout=2;"; //
Notice Connection Timeout set to only two seconds!
conn.Open();
catch(Exception)
conn.ConnectionString = "integrated
security=SSPI;SERVER=YOUR_SERVER;DATABASE=YOUR_DB_NAME;Pool
ing=false;Connect Timeout=45;";
conn.Open();
If I fail to open a pooled connection within two seconds, I am trying to open a non-pooled
connection. This introduces a two second delay when no pooled connections are
available, but if your connection leak doesn't show most of the time, this is a good steam
valve.
Conclusion
In this article you've learned that the most common cause of connection pooling issues is
database connections that are left open or not closed properly. You've learned that when
you type "conn.Close()", you almost always want to put that in the "Finally" block. You
also learned not to interfere with the class destructor unless you use unmanaged
resources. You've learned how to monitor your connection pool and diagnose a potential
problem. You also learned how to keep a system with a connection leak in production if
you really have to, until the problem is resolved. I hope this article has helped you resolve
your connection pooling issue. However, there is more to connection pooling that is not
covered in this article. Check out Bill Vaughn's "Swimming in the .NET connection
pool" at http://www.winnetmag.com/Article/ArticleID/38356/38356.html.
Dmitri Khanine is senior web developer and architect working for a major Canadian
Bank. His 10+ years of experience are mostly in backend and middle tier development of
enterprise Web applications on Microsoft as well as J2EE platforms. Industry experience
includes Banking, Finance, Automotive and software consulting. Dmitri's areas of
interest and expertise include rapid enterprise application development, MVC
frameworks and code generation. Dmitri can be contacted at Khanine@hotmail.com.