• 背景:

在最近开发中遇到一个问题,对一个数据库进行操作时,我采用64个并行的任务每个任务保证一个数据库连接对象;但是每个任务内部均包含有24个文件需要读取,在读取文件之后,我们需要快速将这24个文件批量入库到数据库中。

于是我这样开发我的程序:

主任务处理方式:最多允许64并行主任务;

主任务内部子任务采用串行方式:24个文件依次读取,和当前主任务均使用同一个数据库连接字符串。

每个主任务都需要24个文件入库到各自的物理分表中,采用的是串行读取文件资源,串行入库,没有能并行插入24个批处理文件到当前主任务的分表中,感觉到这可能是数据库IO入库速度不高是一个主要因素。

于是包主任务中的24个文件解析入库子任务改为并行方式,结果问题来了:

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、查看当前数据库已经占用的连接数方法:

A、通过perfiler监控我当前的连接数多少?采用Standard(default)监控模式,stop-》start,每次开始时,就会快速罗列出当前已经建立的连接列表,从列表记录中可以查看到目前数据库实例被占用的数据库连接数。

B、从sys.dm_os_performance_counters中查找

declare @value int;
while 1=1 begin
waitfor delay '00:00:01'
select @value=cntr_value from sys.dm_os_performance_counters where counter_name ='User Connections' print @value;
end

从上边的监控中查询出,目前我们的数据库连接数确实就只有100个左右,怎么就出现连接池满的问题。前50个是系统连接占用,不计算,那么,我们可以使用的连接数只有将近50个就出现连接池满的异常了。

吃惊!

我们查看下数据库连接数设置是否有问题,通过界面查看:

貌似一切正常,没有限制,难道100个连接就达到最大连接数了?!!!

我们执行查询最大连接数查询sql命令:

select * from sys.configurations where name ='user connections'

sqlserver难道在欺骗我们,绝不可能,那么大个公司,如果不能处理这么多,就不会不负责人多高数用户最多允许32767个连接。

我们注意到,这里的value_in_use字段和从数据库界面上看到的一样,都是0,没有限制,那么就是说我们默认就是不受限制,可以最多使用32767个连接。

  • 问题发现:

那么,是谁给我们制定了最大连接数限制为100呢?

记得在数据库连接字符串中是包含这个设置的Max Pool Size属性,赶快查查MSDN,确认下是不是这里不写的话有默认值。

搜索关键字“SqlConnection.ConnectionString 属性”,找打了MSDN:https://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlconnection.connectionstring(VS.80).aspx

名称

默认值

说明

Connection Lifetime

0

当连接被返回到池时,将其创建时间与当前时间作比较,如果时间长度(以秒为单位)超出了由 Connection Lifetime 指定的值,该连接就会被销毁。这在聚集配置中很有用(用于强制执行运行中的服务器和刚置于联机状态的服务器之间的负载平衡)。

零 (0) 值将使池连接具有最大的连接超时。

Connection Reset

'true'

确定从池中提取数据库连接时是否重置数据库连接。对于 SQL Server 7.0 版,设置为 false 可避免获取连接时再有一次额外的服务器往返行程,但须注意此时并未重置连接状态(如数据库上下文)。

只要不将 Connection Reset 设置为 false,连接池程序就不会受到 ChangeDatabase 方法的影响。连接在退出相应的连接池以后将被重置,并且服务器将移回登录时数据库。不会创建新的连接,也不会重新进行身份验证。如果将 Connection Reset 设置为 false,则池中可能会产生不同数据库的连接。

Enlist

'true'

当该值为 true 时,池程序在创建线程的当前事务上下文中自动登记连接。可识别的值为 truefalseyes 和no

Load Balance Timeout

0

连接被销毁前在连接池中生存的最短时间(以秒为单位)。

Max Pool Size

100

池中允许的最大连接数。

Min Pool Size

0

池中允许的最小连接数。

Pooling

'true'

当该值为 true 时,系统将从适当的池中提取 SQLConnection 对象,或在需要时创建该对象并将其添加到适当的池中。可识别的值为 truefalseyes 和 no

当设置需要布尔值的关键字或连接池值时,您可以使用“yes”代替“true”,用“no”代替“false”。整数值表示为字符串。

Max Pool Size 默认为100。

  • 问题验证:

问题终于锁定了,那么是否真的是这样子呢?

我做了一下测试:

     class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(, ); for (var i = ; i < ; i++)
{
ThreadPool.QueueUserWorkItem(Connection);
} while (true)
{
Thread.Sleep();
Console.WriteLine("alive...");
} Console.WriteLine("Complete!!!");
Console.ReadKey();
} private static void Connection(object state)
{
SqlConnection connection = new SqlConnection("Data Source=.;Initial Catalog=i_Master;Persist Security Info=True;User ID=NUser;Password=N2;max pool size=500"); connection.Open(); using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandTimeout = * ;
command.CommandText = @"
SELECT @@VERSION;
waitfor delay '00:00:01'
";
command.CommandType = System.Data.CommandType.Text; command.ExecuteNonQuery();
} Thread.Sleep();
}
}

我设定1000个线程,在.net线程池中运行,每个线程打开数据库连接字符串后不关闭,让他永久占用连接,直到对象被回收或者连接超时。

通过上边两种监控连接的方式,查看到的结果:

A方式监控结果:

B方式监控结果:

  • 参考资料:

Configure the user connections Server Configuration Option:https://technet.microsoft.com/en-us/library/ms187030.aspx

Connection Pooling and the “Timeout expired” exception FAQ:https://blogs.msdn.microsoft.com/angelsb/2004/08/25/connection-pooling-and-the-timeout-expired-exception-faq/

Max Connection Pool capped at 100:http://dba.stackexchange.com/questions/51219/max-connection-pool-capped-at-100

SqlConnection.ConnectionString 属性:https://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlconnection.connectionstring(VS.80).aspx

SQLSERVER: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. 网站错误记录:Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool.

    今天看公司项目的错误日志文件,发现日志文件都是记录的这个错误. 经过网站查找,发现英文翻译是: 译:超时,与连接池的连接时间已过.这种情况发生是因为连接池在使用和最大连接池数目已满 通过翻译,可以看出 ...

  2. SSRS 2008 R2 错误:Timeout expired. The timeout period

    今天遇到了Reporting Services(SQL SERVER 2008 R2)的报表执行异常情况,报表加载数据很长时间都没有响应,最后报"An error occurred with ...

  3. Connection open error . Connection Timeout Expired. The timeout period elapsed during the post-login phase.

    是这样的,最近我在开发Api(重构),用的数据库是Sqlserver,使用的Orm是 SqlSugar(别问我为什么选这个,boss选的同时我也想支持国人写的东西,且文档也很全). 被催的是,写好了程 ...

  4. Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

    今天碰到了一个查询异常问题,上网查了一下,感谢原创和译者 如果你使用的数据库连接类是 the Data Access Application Blocks "SqlHelper" ...

  5. Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.【转】

    今天碰到了一个查询异常问题,上网查了一下,感谢原创和译者 如果你使用的数据库连接类是 the Data Access Application Blocks "SqlHelper" ...

  6. 记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法

    记一次查询超时的解决方案The timeout period elapsed...... https://www.cnblogs.com/wyt007/p/9274613.html Exception ...

  7. 解决 Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 的问题

    在web 网站开发中,经常需要连接数据库,有时候会出现这样的数据连接异常消息: 主要原因是 应用程序与数据库的连接超出了数据库连接的默认时长,在这种情况下,我们可以把数据库连接的时长延长一些,因为 C ...

  8. [bug]Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding

    写在前面 在mysql中这个异常是非常常见的,超时分为连接超时和执行超时,而连接超时,大部分原因是网络问题,或客户端到服务端的端口问题造成. bug场景 有的时候,使用MySqlDataReader在 ...

  9. The timeout period elapsed prior to completion of the operation or the server is not responding.

    问题:更新数据的状态值时,部分报出如下异常: 即时有成功更新,时有报错问题出现. 在LOG中发现成功更新的数据,存在更新时间过长问题,将近30秒(EF默认的CommandTimeout为30秒): 代 ...

随机推荐

  1. 1、C到C++安全性增强

    1.C语言 #include <stdio.h> int main(void) { const int a = 10; //在C语言里这里不赋值可以编译的过去,但是这里不初始化以后就没办法 ...

  2. oracle case when 语句

    原文:http://www.cnblogs.com/eshizhan/archive/2012/04/06/2435493.html CASE WHEN 表达式有两种形式 简单Case函数 CASE ...

  3. hdf第一周完了,突然时间静止.,醒了就早点去公司上班,再努力一点

    周一要了个任务,做评价完成,分享完成的页面,做到周四发现可能做不出来,找dzy,逻辑比较混乱,想要放弃了,感觉自己非常没用.昨天跟豆聊了一下,否定自己是一点意义也没有的,觉得自己很差劲,无助的感觉跟初 ...

  4. ubuntu挂载其他分区到/home下,将当前分区内容替换

    有时候,我们装系统时,可能因为没注意,把某一个分区分小了,导致到最后,我们的那个盘容不下了, 这时,面临的两个选择就是:要么卸载一些软件,要么重新分区,重装系统,其实,还可以这样,去把其他 多余的盘分 ...

  5. extjs4 树列表 添加子节点 刷新所有父节点数据

    itemclick:function(view, record, item,index){console.log(record.parentNode) for(pNode = record.paren ...

  6. Eclipse下使用Ant 【转】

    官方在线帮助文档:http://ant.apache.org/manual/index.html 中文汉化 帮助文档:http://www.cnblogs.com/pengxl/archive/201 ...

  7. Bluetooth数据包捕获

    目录 1. 前提 2. 开启功能 3. 抓包 这里介绍一种在Android上捕获蓝牙数据包的方法 1. 前提 首先你要有一部Android手机 然后你的Android系统版本要在4.4及以上 我没有做 ...

  8. SQL查询的几种方式

    /* 左连接 left join 或者 left outer join */ /* 左连接 Table_A表数据全部显示,Table_B根据条件匹配Table_A 匹配上显示,否则显示NULL */ ...

  9. ManualResetEvent和AutoResetEvent的区别实例

    ManualResetEvent和AutoResetEvent的作用可以理解为在线程执行中插入停顿点flag终止程序运行,然后通过设置flag的状态来使得程序继续运行. 两者的区别是:ManualRe ...

  10. There is no tracking information for the current branch

    There is no tracking information for the current branch. Please specify which branch you want to mer ...