问题描述我们获取连接超过连接池最大值时产生如上异常。通常连接池最大值为100。当我们获取连接超过最大值时,WEB等待连接池返回连接而超时,这样将抛出如上异常
解决办法:首先要做的是在我们使用连接后立即关闭连接。如果没有关闭连接那么连接将保存到连接池中直到垃圾回收(Garbage Collection)来销毁。这种情况下你以为连接池没有到达最大值,但实际上连接池已经到达了最大值,其次我们可以通过连接字符串中的MaxPoolSize = N;来动态扩大连接池中的连接最大数量。

说明: 也就是在connectionString中如果未指定maxpoolsize的值,则maxpoolsize=100,当访问人员同时连接数据库的数量为101人时,则等待SqlConnection.ConnectionTimeout设置的时间(默认是15 秒)后,还是没有可用的Connection则会出现上面的错误。

Connection Pool 是什么呢 ?
每当程序需要读写数据库的时候。Connection.Open()会使用ConnectionString连接到数据库,数据库会为程序建立 一个连接,并且保持打开状态,此后程序就可以使用T-SQL语句来查询/更新数据库。当执行到Connection.Close()后,数据库就会关闭当 前的连接。很好,一切看上去都是如此有条不紊。
但是如果我的程序需要不定时的打开和关闭连接,(比如说 ASP.Net 或是 Web Service ),例如当Http Request发送到服务器的时候,我们需要打开Connection 然后使用Select* from Table 返回一个DataTable/DataSet给客户端/浏览器,然后关闭当前的Connection。那每次都Open/Close Connection 如此的频繁操作对于整个系统无疑就成了一种浪费
ADO.Net Team就给出了一个比较好地解决方法。将先前的Connection保存起来,当下一次需要打开连接的时候就将先前的Connection 交给下一个连接。这就是Connection Pool。
Connection Pool 如何工作的?

首先当一个程序执行Connection.open()时候,ADO.net就需要判断,此连接是否支持Connection Pool (Pooling 默认为True),如果指定为False, ADO.net就与数据库之间创建一个连接(为了避免混淆,所有数据库中的连接,都使用”连接”描述),然后返回给程序。

如果指定为 True,ADO.net就会根据ConnectString创建一个Connection Pool,然后向Connection Pool中填充Connection(所有.net程序中的连接,都使用”Connection”描述)。填充多少个Connection由Min Pool Size (默认为0)属性来决定。例如如果指定为5,则ADO.net会一次与SQL数据库之间打开5个连接,然后将4个Connection,保存在 Connection Pool中,1个Connection返回给程序。

 当程序执行到Connection.close() 的时候。如果Pooling 为True,ADO.net 就把当前的Connection放到Connection Pool并且保持与数据库之间的连接。同时还会判断Connection Lifetime(默认为0)属性,0代表无限大,如果Connection存在的时间超过了Connection LifeTime,ADO.net就会关闭的Connection同时断开与数据库的连接,而不是重新保存到Connection Pool中。(这个设置主要用于群集的SQL 数据库中,达到负载平衡的目的)。
如果Pooling指定为False,则直接断开与数据库之间的连接。
 
然后当下一次Connection.Open() 执行的时候,ADO.Net就会判断新的ConnectionString与之前保存在Connection Pool中的Connection的connectionString是否一致。(ADO.Net会将ConnectionString转成二进制流,新的ConnectionString与保存在Connection Pool中的Connection的ConnectionString必须完全一致,即使多加了一个空格,或是修改了Connection String中某些属性的次序都会让ADO.Net认为这是一个新的连接,而从新创建一个新的连接。所以如果您使用的UserID,Password的认证方式,修改了Password也会导致一个Connection,如果使用的是SQL的集成认证,就需要保存两个连接使用的是同一个)。

然后 ADO.net需要判断当前的Connection Pool中是否有可以使用的Connection(没有被其他程序所占用),如果没有的话,ADO.net就需要判断ConnectionString设置的Max Pool Size (默认为100),如果Connection Pool中的所有Connection没有达到MaxPoolSize,ADO.net则会再次连接数据库,创建一个连接,然后将Connection返回给程序。

如果已经达到了 MaxPoolSize,ADO.net就不会再次创建任何新的连接,而是等待Connection Pool中被其他程序所占用的Connection释放,这个等待时间受SqlConnection.ConnectionTimeout(默认是15 秒)限制,也就是说如果时间超过了15秒,SqlConnection就会抛出超时错误(所以有时候如果SqlConnection.open()方法抛 出超时错误,一个可能的原因就是没有及时将之前的Connnection关闭,同时Connection Pool数量达到了MaxPoolSize。)

如果有可用的Connection,从Connection Pool 取出的Connection也不是直接就返回给程序,ADO.net还需要检查ConnectionString的ConnectionReset属性 (默认为True)是否需要对Connection 最一次reset。这是由于,之前从程序中返回的Connection可能已经被修改过,比如说使用 SqlConnection.ChangeDatabase method 修改当前的连接,此时返回的Connection可能就已经不是连接当前的Connection String指定的Initial Catalog数据库了。所以需要reset一次当前的连接。但是由于所有的额外检查都会增大ADO.net Connection Pool 对系统的开销。

【WEB】原理 之 线程池的更多相关文章

  1. 如何决定Web应用的线程池大小

    线程池(Thread Pool)在Web应用中线程池的大小决定了在任何一个时间点应用可以处理请求的并发数.如果一个系统收到的请求数超过了线程池的大小,那么超出的请求要么进入等待队列要么被拒绝.请注意, ...

  2. 如何决定 Web 应用的线程池大小

    在部署 web 应用到生产环境,或者在对 web 应用进行性能测试的时候,经常会有人问:如何决定 web 应用线程池大小?决定一个 IO 阻塞型 web 应用的线程池大小是一项很艰巨的任务.通常是通过 ...

  3. SpringBoot异步使用@Async原理及线程池配置

    前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢 使用步骤 完成异步操作一般有两种 ...

  4. 线程池的概念&原理和线程池的代码实现

    线程池:一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源.工作原理:可以用一张图来简洁明了说明: 合理利用线程池能够带来三个好处∶1.降低 ...

  5. Java原理领悟-线程池(Executor)

    线程池全面解析 什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用. 线程池的好处 我 ...

  6. Executor线程池原理详解

    线程池 线程池的目的就是减少多线程创建的开销,减少资源的消耗,让系统更加的稳定.在web开发中,服务器会为了一个请求分配一个线程来处理,如果每次请求都创建一个线程,请求结束就销毁这个线程.那么在高并发 ...

  7. hystrix线程池隔离的原理与验证

    引子 幸福很简单: 今天项目半年规划被通过,终于可以早点下班.先坐公交,全程开着灯,买了了几天的书竟然有时间看了.半小时后,公交到站,换乘大巴车.车还等着上人的功夫,有昏暗的灯光,可以继续看会儿书.过 ...

  8. 一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 31.线程池复用的原理 32.spring是什么? 33.对Aop的理解 34.对IOC的理解 35.BeanFactor ...

  9. Java线程池使用和分析(二) - execute()原理

    相关文章目录: Java线程池使用和分析(一) Java线程池使用和分析(二) - execute()原理 execute()是 java.util.concurrent.Executor接口中唯一的 ...

随机推荐

  1. 225. Implement Stack using Queues

    代码如下: class MyStack { // Push element x onto stack. Queue<Integer> queue=new ArrayDeque<> ...

  2. MySQL复制的基本概念和实现

    MySQL的复制的概念是完成水平扩展的架构 MySQL性能方面的扩展方式有scale on(向上扩展,垂直扩展)                          scale out(向外扩展,水平扩 ...

  3. 越狱Season 1-Season 1, Episode 3: Cell Test

    Season 1, Episode 3: Cell Test -CO: Oh, my God. 我的天 Williamson, get in here. Williamson 快进来 What the ...

  4. ARM1138@库函数速查

    1. GPIO库函数 可实现的功能: 获得/设置指定管脚的方向(输入.输出)和模式(硬件控制) 获取/设置指定管脚的配置(驱动强度2/4/8/8_SCmA.管脚模式:推挽(弱上拉/弱下拉)/开漏(弱上 ...

  5. Java——集合框架 工具

     /* * Arrays工具类的使用 */ public class ArraysTest { public static void main(String[] args) { // TODO A ...

  6. phpstorm编辑器智能提示框架代码

    按照上面的步骤就可以智能提示代码了!

  7. 有关<table>的几个问题

    1)实现任意一行下边框的颜色设置: 单元格边距(表格填充)(cellpadding) -- 代表单元格外面的一个距离,用于隔开单元格与单元格空间 单元格间距(表格间距)(cellspacing) -- ...

  8. Unity3d NGUI 地图

    1,制作地图 方式1: NGUI,新建一个Atlas,为M,按照一定的比例如 1:400,绘制地图. 新建一个GameObject,为A,关联UIPanel.A的transform.localScal ...

  9. 最大化 AIX 上的 Java 性能,第 4 部分: 监视流量

    http://www.ibm.com/developerworks/cn/aix/library/es-Javaperf/es-Javaperf4.html 最大化 AIX 上的 Java 性能,第 ...

  10. python2.7处理https稍微好点的办法(坑得一笔)

    from warnings import filterwarnings filterwarnings('ignore') r = requests.get(url, headers=headers, ...