在大多数情况下,连接池问题与连接泄漏有关。应用程序可能无法正确且一致地关闭数据库连接。当您保持连接打开时,它们将保持阻塞状态,直到. net垃圾回收器通过调用Finalize()方法为您关闭它们。
你要确保你真的关闭了连接。例如,如果.Open和Close之间的代码抛出异常,下面的代码将导致连接泄漏:
var connection = new SqlConnection(connectionString);
connection.Open();
// some code
connection.Close();
正确的方法是这样的:
var connection = new SqlConnection(ConnectionString);
try
{
connection.Open();
someCall (connection);
}
finally
{
connection.Close();
}
or
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
someCall(connection);
}
当你的函数从一个类方法返回一个连接时,确保你在本地缓存它并调用它的Close方法。您将使用以下代码泄漏一个连接,例如:
var command = new OleDbCommand(someUpdateQuery, getConnection());
result = command.ExecuteNonQuery();
connection().Close();
第一次调用getConnection()返回的连接没有被关闭。这一行不会关闭连接,而是创建一个新的连接并尝试关闭它。
如果您使用SqlDataReader或OleDbDataReader,请关闭它们。尽管关闭连接本身似乎就能达到目的,但在使用数据读取器对象时,还是要花费额外的精力显式关闭它们。
这篇来自MSDN/SQL杂志的文章“为什么连接池溢出?”解释了很多细节,并建议了一些调试策略:
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.