如何解决ASP.NET和SQL Server之间的连接池问题?
最近几天我们在我们的网站上看到这个错误消息太多了:
“Timeout expired。在从池中获取连接之前已经超时了,这可能是因为所有连接池都在使用中,并且达到最大池大小。
我们在一段时间内没有改变我们的代码中的任何东西。 我修改了代码来检查打开的连接没有closures,但发现一切正常。
-
我该如何解决这个问题?
-
我需要编辑这个池吗?
-
如何编辑此池的最大连接数?
-
高stream量网站的build议价值是多less?
更新:
我需要在IIS中编辑一些东西吗?
更新:
我发现活动连接的数量是从15到31的任何地方,我发现在SQL服务器中configuration的连接的最大允许数量超过3200个连接,是31太多,或者我应该编辑ASP.NET configration ?
在大多数情况下,连接池问题与“连接泄漏”有关。 您的应用程序可能不会正确和一致地closures其数据库连接。 当您打开连接时,它们将保持阻塞状态,直到.NET垃圾收集器通过调用它们的Finalize()
方法closures它们为止。
你想确保你真的closures了连接 。 例如,如果.Open
和Close
之间的代码引发exception,则以下代码将导致连接泄漏:
var connection = new SqlConnection(connectionString); connection.Open(); // some code connection.Close();
正确的方法是这样的:
var connection = new SqlConnection(ConnectionString); try { connection.Open(); someCall (connection); } finally { connection.Close(); }
要么
using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); someCall(connection); }
当你的函数从一个类方法返回一个连接时,确保你在本地caching并调用它的Close
方法。 您将使用此代码泄漏连接,例如:
var command = new OleDbCommand(someUpdateQuery, getConnection()); result = command.ExecuteNonQuery(); connection().Close();
从第一次调用getConnection()
返回的连接没有被closures。 而不是closures你的连接,这条线创build一个新的,并试图closures它。
如果您使用SqlDataReader
或OleDbDataReader
,closures它们。 即使closures连接本身似乎也有诀窍,但在使用它们时要特别closures数据读取器对象。
MSDN / SQL杂志中的这篇文章“ 为什么连接池溢出? ”解释了很多细节并提出了一些debugging策略:
- 运行
sp_who
或sp_who2
。 这些系统存储过程从sysprocesses
系统表中返回信息,显示所有工作进程的状态和信息。 通常,每个连接都会看到一个服务器进程ID(SPID)。 如果您使用连接string中的“应用程序名称”参数来命名连接,则您的工作连接将很容易find。 - 使用SQL Server Profiler和SQLProfiler
TSQL_Replay
模板来跟踪打开的连接。 如果您熟悉Profiler,则此方法比使用sp_who进行轮询更容易。 - 使用性能监视器来监视池和连接。 我稍后讨论这个方法。
- 用代码监视性能计数器。 您可以通过使用例程提取计数器或使用新的.NET PerformanceCounter控件来监视连接池的健康状况和build立的连接数。
在安装.NET Framework v4.6.1后, 由于此更改,我们与远程数据库的连接立即开始超时。
要修复,只需在连接string中添加参数TransparentNetworkIPResolution
并将其设置为false :
服务器= myServerName;数据库= MyDatabase的; Trusted_Connection = TRUE; TransparentNetworkIPResolution =假
除非你的使用量增加很多,否则似乎不太可能只有积压的工作。 国际海事组织,最有可能的select是,有些东西正在使用连接,而不是及时发布。 你确定你在使用所有的情况吗? 或者(通过任何机制)释放连接?
您是否在closures连接或数据读取器之前检查没有closures的DataReader和response.redirects。 在redirect之前不要closures它们时,连接保持打开状态。
我们不时在我们的网站上遇到这个问题。 在我们的情况下,罪魁祸首是我们的统计/索引越来越过时。 这会导致以前快速运行的查询(最终)变慢和超时。
尝试更新统计信息和/或重build受查询影响的表上的索引,看看是否有帮助。
您可以通过在连接string中指定MinPoolSize=xyz
和/或MaxPoolSize=xyz
来指定最小和最大池大小。 这个问题的原因可能是另一回事。
在我的一个.NET应用程序中使用某些第三方数据层时,我也遇到了这个问题。 问题在于该层没有正确closures连接。
我们抛出了层,并创build了一个自己,总是closures和configuration连接。 从那以后,我们不再犯错误了。
用这个:
finally { connection.Close(); connection.Dispose(); SqlConnection.ClearPool(); }
如果您正在使用复杂的遗留代码(使用简单的使用(..){..})是不可能的 – 就像我一样 – 您可能需要查看我在这个SO问题中发布的代码片段,以确定在连接可能泄漏时调用连接创build堆栈(在设置超时后不closures)。 这使得发现泄漏的原因相当容易。
这主要是由于应用程序中的连接没有closures。 在连接string中使用“MinPoolSize”和“MaxPoolSize”。
不要多次实例化sql连接。 打开一个或两个连接,并将其用于所有下一个SQL操作。
似乎即使在抛出连接时抛出exception。
在我的情况下,我没有closuresDataReader对象。
using (SqlCommand dbCmd = new SqlCommand("*StoredProcedureName*")) using (dbCmd.Connection = new SqlConnection(WebConfigurationAccess.ConnectionString)) { dbCmd.CommandType = CommandType.StoredProcedure; //Add parametres dbCmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = ID; ..... ..... dbCmd.Connection.Open(); var dr = dbCmd.ExecuteReader(); //created a Data reader here dr.Close(); //gotta close the data reader //dbCmd.Connection.Close(); //don't need this as 'using' statement should take care of this in its implicit dispose method. }
你的代码泄露了连接。 您可以尝试使用来certificate您正在closures它们。
Using (SqlConnection sqlconnection1 = new SqlConnection(“Server=.\\SQLEXPRESS ;Integrated security=sspi;connection timeout=5”)) { sqlconnection1.Open(); SqlCommand sqlcommand1 = sqlconnection1.CreateCommand(); sqlcommand1.CommandText = “raiserror ('This is a fake exception', 17,1)”; sqlcommand1.ExecuteNonQuery(); //this throws a SqlException every time it is called. sqlconnection1.Close(); //Still never gets called. } // Here sqlconnection1.Dispose is _guaranteed_
这个问题我以前遇到过。 它最终成为了防火墙的一个问题。 我刚刚添加了一个规则到防火墙。 我不得不打开端口1433
所以SQL服务器可以连接到服务器。
这个问题我在我的代码。 我将粘贴一些示例代码,我已经结束了错误。 在从池中获取连接之前已经超时。 发生这种情况的原因可能是因为所有连接池都在使用中,并且达到最大池大小。
String query = "insert into STATION2(ID,CITY,STATE,LAT_N,LONG_W) values('" + a1 + "','" + b1 + "','" + c1 + "','" + d1 + "','" + f1 + "')"; //,'" + d1 + "','" + f1 + "','" + g1 + "' SqlConnection con = new SqlConnection(mycon); con.Open(); SqlCommand cmd = new SqlCommand(); cmd.CommandText = query; cmd.Connection = con; cmd.ExecuteNonQuery(); **con.Close();**
您想每次closures连接。 在此之前,我没有closures连接,因为我得到了错误。 加了closures声明后,我已经结束了这个错误