赞
踩
这是一篇转载,参考原文在:https://blogs.msdn.microsoft.com/angelsb/2004/08/25/connection-pooling-and-the-timeout-expired-exception-faq/
https://blog.csdn.net/marklr/article/details/4325699
客户在IIS上建立了WebApp,间歇性会发生异常,异常信息为:
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.
从字面上理解就是因为连接超时,可能原因是最大连接数已满。常见的原因主要有三种:
1.You use more than Max Pool Size connections (Max Pool Size default=100)
This is fairly rare in most applications, 100 concurrent connections is a very large number when you are using pooling. In my experience the only time this has been the cause of the exception above is when you open all 100 connections in a single thread as shown below:
SqlConnection[] connectionArray = new SqlConnection[101];
for (int i = 0; i <= 100; i++)
{
connectionArray[i] = new SqlConnection("Server=.\\SQLEXPRESS ;Integrated security=sspi;connection timeout=5");
connectionArray[i].Open();
}
Solution: Once you have determined that you are using more than 100 concurrent connections (with the same connection string) you can increase Max Pool Size.
2.You are leaking connections
My definition of a leaked connection is a connection that you open but you do not Close OR Dispose explicitly in your code. This covers not only the times when you forget to make the connection.Close() or Dispose() call in your code, but the much harder to catch scenarios where you do call connection.Close but it does not get called! See below:
using System;
using System.Data;
using System.Data.SqlClient;
public class Repro
{
public static int Main(string[] args) { Repro repro = new Repro(); for (int i = 0; i <= 5000; i++) { try{ Console.Write(i+" "); repro.LeakConnections(); } catch (SqlException){} } return 1; } public void LeakConnections() { 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(); //We are calling connection close, and we are still leaking connections (see above comment for explanation) }
}
Paste this code into visual studio and place a breakpoint in the sqlconnection1.Close(); line, it will never get called since ExecuteNonQurery throws an exception. After a short while you should see the dreaded Timeout exception, in my computer it happens at around 170 connections. This is definitely a contrived example, I am stacking the deck by lowering the connection timeout and throwing an exception every call, but when you consider moderate to heavy load on an ASP.NET application any leak is going to get you in trouble.
3.You are rapidly opening or closing connections with sql debugging enabled in Visual Studio.
There is a known bug with Visual Studio 2003 and Sql Debugging, take a look at http://support.microsoft.com/default.aspx?scid=kb;en-us;830118
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。