连接池和 "Timeout expired"异常【转】
异常信息:
MySql.Data.MySqlClient.MySqlException (0x80004005): error connecting: 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.
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at ArticleSys.MySqlHelper.PrepareCommand(MySqlCommand cmd, MySqlConnection conn, MySqlTransaction trans, CommandType cmdType, String cmdText, MySqlParameter[] cmdParms)
at ArticleSys.MySqlHelper.GetDataTable(String mysqlConnStr, CommandType cmdType, String cmdText, MySqlParameter[] commandParameters)
=====================2013-10-10 12:28:33==============
------------以下为正文
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.
Timeout expired 异常是个很棘手的异常,想必几乎每个人都碰到过。有时可真是对它咬牙切齿,拿它没办法。 angelsb这篇文章很好,希望对大家有用。我也是看到他讲得很好,才翻译过来的,水平有限,请多多指教.
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.
哎!在另一个进程中,又出现了连接池已满的问题,这是个最让人头痛却又是最常出现的连接池问题之一.原因是在开发过程中很少碰到这个头痛的问题,但在部署APP到客户端时,却总是不经意地跑出来了.我想,我应该花些许时间对这个问题进行一次完整的总结吧.
发生的本质是什么?
我们来认真看一下可能会发生这种异常的两种情况
1) 你使用了超过最大的连接池连接数(默认的最大连接数是100)
在大部分应用程序中,这种情况是很少出现的. 毕竟当你使用连接池时,100个并行连接是一个非常大的数字.根据我的经验,会造成这种异常的原因的最大可能,应该是在一个纯种下打开了100个连接.
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();
}
解决方案:如果你确定你将会使用超过100个并行连接(在同一连接字符串上),你可以增加最大连接数.
2) 连接泄漏
我个人认为的连接泄漏定义是你打开了一个连接但你没有在你的代码中执行close()或dispose().这范围不仅仅是你忘记了在connection后连接后使用dispose()或close()对期进行关闭,还包括一些你已经在相关connection后写好了close()却根本没有起作用的情況.我们来看看下面的代码:
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)
}
}
这就是一个典型的例子,将这段代码复制到visual Studio中,在 sqlconnection1.close()中设置一个断点,编译时可以看到他永远没有执行,因为ExecuteNonQurery抛出了一个异常.之后你应该可以看到恐怖的超时异常了. 在我的机子上,大约有170个连接被打开. 我曾想让其在每次调用的时候将异常抛出来达到降低连接超时出现的机率,但当你考虑到将其部署到一个ASP.NET的应用程序的时候,任何一个泄漏都将让你处于麻烦之中.
3)你是通过visual Studio中的sql debugging 来打开或关闭连接的
这是一个众所周知的Bug,可以看一下下面这个链接
http://support.microsoft.com/default.aspx?scid=kb;en-us;830118
如何在ADO.NET2.0中判断是否是连接泄漏
在1.0或1.1中,我们很难去判断是否是连接泄漏,至多可以通过一些性能指标或诸如此类的工作去实现.但在ADO.NET2.0中,如果你注意到NumberOfReclaimedConnections这个玩艺儿,就可以知道你的应用程序是否是连接泄漏了.
时刻注意修复相关的连接字符串
修改相关的连接字符串可以让你暂时翻译”逃过”一些异常,这是非常诱人的.特别是在一个高性能消耗时,修改它就显示更为必要了.
这里是一些让你的应用程序能”运行良好”的非正常行为(搬起石头砸自己的脚)
不要把Poooling=False
坦白的说,如果你将pooling设为关闭状态,你当然不会再碰到超时异常,可怕的是你的应用程序性能将大大降低,而你的连接仍然处于泄漏状态.
不要把Connection LifeTime=1
这不是一个能清除异常的方法,但它可能是最接近的一个解决方法.你想告诉我们的是将所有的连接超过一秒钟的连接都通通抛弃(正常的生命周期结束应该是在connetcio.close()后).我个人认为这种方法上关闭连接池没什么两样.除非你是在使用数据库的集群,否则你不应设置连接周期来达到目的.
不要将 Connection TimeOut=40000
非常愚蠢的选择,你这是在告诉我们在抛出一个超时异常之前,你在无限地等待一个连接转变为可用的.幸亏在ASP.NET中将会在三分钟之后取消一个进程.
不要将Max PoolSize=4000;
如果你将连接池的最大数设置到足够大的时候,你最终会将这异常停止.但在另一方面,你将占用了你的应用程序中才是真正需要的巨大的连接资源,这种做法只能饮鸠止渴.
解决方案:
你需要保证你每次调用连接的同时都在使用过后通过close()或dispose()对其执行了关闭.最简单的办法就是使用using,将你的连接泄漏方法修改成如下面的代码样式:
public void DoesNotLeakConnections()
{
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_
}
FAQ:
Q:为什么要这样做
A:使用using结构等同于Try/…/Finally{ .Dispose() ) 即使当ExecuteNonQuery会抛出一个执行错误时,我们都可以保证finally模块将会执行
Q:我上面的代码中如果没有异常抛出的话,我可以使用close()或dispose()吗
A:我们毫无顾忌地用他们中的任意一个,或两个同时使用.在一个已经close或dipose()的连接中使用close()或dispose()是不会影响的
Q:Close()和Dispose()有什么不同,我应该用哪一个好?
A:它们做的是同一件事,你可以调用他们中的任意一个,或两个同时使用.
Q:你所说的"practically the same thing”是什么意思?
A:Dispose()将会通过sqlConnection来清理相关的连接,之后执行close().它们没有什么本质的区别,你可以通过reflector来证明这点
Q:与close()相比,connection.dispose()会将连接些移除吗?
A:不会
---------------------------------------------------------------
我的分享:
针对"Timeout expired"这个异常,我也查阅了很多资料。在国内我们很多project都会采用MS提供的sqlhelper这个封装类。因为这个类中有本身的缺陷所致,所以出现的"Timeout expiered"异常机率大。我在国外的一篇文章中看到的解决方案是:
将SqlHelper中的cmd.CommandTimeout="你要设置的秒数"加上去,重新编译.
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = cmdType;
cmd.CommandTimeout = 240;
通过搜索,我找到了相关的一个代码.
这个代码是摘自国人的某位同行的,感谢
http://blog.csdn.net/long2006sky/archive/2007/07/09/1683459.aspx
eg:
**////
/// 执行查询语句,返回DataTable
///
/// 查询语句
/// 设置查询Timeout
/// 用于复杂查询
public static DataTable GetDataTable(string SQLString,int commTime)
...{
string connectionString = System.Configuration.ConfigurationManager.AppSettings["connectionString"];
using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString))
...{
DataTable dt = new DataTable();
try
...{
connection.Open();
System.Data.SqlClient.SqlDataAdapter da = new System.Data.SqlClient.SqlDataAdapter();
System.Data.SqlClient.SqlCommand comm = new System.Data.SqlClient.SqlCommand(SQLString, connection);
comm.CommandTimeout = commTime;
da.SelectCommand = comm;
da.Fill(dt);
}
catch (System.Data.SqlClient.SqlException ex)
...{
throw new Exception(ex.Message);
}
return dt;
}
}
连接池和 "Timeout expired"异常【转】的更多相关文章
- 连接池和 "Timeout expired"异常
转自:博客园宁静.致远:http://www.cnblogs.com/zhangzhu/archive/2013/10/10/3361197.html 异常信息: MySql.Data.MySqlCl ...
- HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查
转自: http://blog.csdn.net/shootyou/article/details/6615051 今天解决了一个HttpClient的异常,汗啊,一个HttpClient使用稍有不慎 ...
- Timeout expired超时时间已到. 达到了最大池大小 错误及Max Pool Size设置
此文章非原创,仅为分享.学习!!! 参考数据库链接串: <add key="data" value="server=192.168.1.123; port=3306 ...
- Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置
参考数据库链接串: <add key="data" value="server=192.168.1.123; Port=3306; uid=root; pwd=ro ...
- error connecting: Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置
[参考]Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置 [参考][数据库-MySql] MySqlConnection error connec ...
- mysql连接池不能回避的wait timeout问题(转)
起因 我们的项目组一直在使用albianj作为开发框架在开发应用.使用至今倒也是没有出现很大的问题,但最近加过监控的接口基本上都会在使用一段时间后,突然之间执行数据库操作变得很慢.虽然会变慢,但持续的 ...
- Java Mysql连接池配置和案例分析--超时异常和处理
前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...
- druid连接池异常
在从excel导入10W条数据到mysql中时,运行一段时间就会抛这个异常,连接池问题 org.springframework.transaction.CannotCreateTransactionE ...
- 存储过程 务的概念 事务的特性 关于异常的处理 连接池 构JdbcUtil类
1 存储过程 1)用当地数据库语言,写的一段业务逻辑算法,并该算法存储在客户端 2)使用存储过程需要用于CallableStatement接口,同时需要使如下SQL命令调用:{call a ...
随机推荐
- [转]Squid中的日志出现TCP_CLIENT_REFRESH_MISS的问题排除
转自:http://www.php-oa.com/2008/07/15/tcp_client_refresh_miss.html 今天检查Squid发现大量的日志出现TCP_CLIENT_REFRES ...
- [shell基础]——find命令
find命令选项 -name 按照文件名查找 -type 查找某一类型的文件(b 代表设备块:d 目录:c 字符设备文件:l 符号(软)链接文件:f 普通文件) -size 查找文件长度或者大小 -p ...
- svn版本控制器在vs2013中的使用
下面记录常用的几种用法: a) SVN检出 将SVN服务端所保存的数据下载到个人工作平台. 组长上传初始项目后,各组员可以到服务器上检出项目 1. 打开Visual Studio 2010-& ...
- Daily Scrum4
今天我们小组开会内容分为以下部分: part1:与负责这个项目的其他组进行会晤; part2:组内成员召开了简短会议,进行工作安排; part3:总结今日工作,对项目遇到的问题商讨解决办法; ◆Par ...
- Daily Scrum3
今天我们小组开会内容分为以下部分: part 1: 汇报之前分配的任务进度: part 2:分配明天的任务. ◆Part 1 组员进度报告 彭佟小组完成的优化目标: 关于软件防滥用及垃圾信息拦 ...
- 你所必须掌握的三种异步编程方法callbacks,listeners,promise
目录: 前言 Callbacks Listeners Promise 前言 coder都知道,javascript语言运行环境是单线程的,这意味着任何两行代码都不能同时运行.多任务同时进行时,实质上形 ...
- 使用Java 8 API,根据传递的分隔符,连接list中所有的元素
public class MethodReferenceDemo1 { @FunctionalInterface interface StringListFormatter { String form ...
- Java8 Lambda sample (iwantmoon.com出品)
转载请注明出处:http://iwantmoon.com/Post/83a4497a74674612834965857e7bc044 .Net转到Java来,不知不觉已经有两年了,之前已经用习惯的li ...
- 图解SQL的Join(转摘)
转摘网址:http://coolshell.cn/articles/3463.html 对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的 ...
- 802.11 wireless 五
802.11 wireless 5CSMA/CA,采用倒计时的方法,退避的时间(当年时间+duration 为发送时间,每一个帧会有一个duration,这个位叫做duration[n.持续]) PS ...