Ado.net中SQLServer数据库连接池

相关资源:

  1. https://www.cnblogs.com/7qi7/articles/2342494.html
  2. https://www.cnblogs.com/lonelyxmas/p/11229038.html
  • MSDN解释

连接到数据库服务器通常由几个需要很长时间的步骤组成。 必须建立物理通道(例如套接字或命名管道),必须与服务器进行初次握手,必须分析连接字符串信息,必须由服务器对连接进行身份验证,必须运行检查以便在当前事务中登记,等等。

实际上,大多数应用程序仅使用一个或几个不同的连接配置。 这意味着在执行应用程序期间,许多相同的连接将反复地打开和关闭。 为了使打开的连接成本最低,ADO.NET 使用称为连接池的优化方法。

连接池减少新连接需要打开的次数。 池进程保持物理连接的所有权。 通过为每个给定的连接配置保留一组活动连接来管理连接。 只要用户在连接上调用 Open,池进程就会检查池中是否有可用的连接。 如果某个池连接可用,会将该连接返回给调用者,而不是打开新连接。 应用程序对该连接调用 Close 时,池进程会将连接返回到活动连接池集中,而不是真正关闭连接。 连接返回到池中之后,即可在下一个 Open 调用中重复使用。

只有配置相同的连接可以建立池连接。 ADO.NET 同时保留多个池,每个配置一个池。 连接由连接字符串以及 Windows 标识(在使用集成的安全性时)分为多个池。 还根据连接是否已在事务中登记来建立池连接。

池连接可以显著提高应用程序的性能和可缩放性。 默认情况下,ADO.NET 中启用连接池。除非显式禁用,否则,连接在应用程序中打开和关闭时,池进程将对连接进行优化。 还可以提供几个连接字符串修饰符来控制连接池的行为。

  • 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没有达到Max Pool Size,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 对系统的开销。

  • 查看应用程序池占用数量:

select * from sysprocesses where dbid= db_id(‘数据库名‘)

Max Pool Size:如果未设置则默认为100,理论最大值为32767。最大连接数是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。在等待队列中,默认等待与服务器的连接的时间为15秒。

中文错误:

超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

英文错误:

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.

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

说明:

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

当我们设置为:

"Server=(local); Integrated Security=SSPI; Database=Northwind; Max Pool Size=512; Min Pool Size=5"  时。则访问人员同时连接数据库的数量为513时,则等待SqlConnection.ConnectionTimeout设置的时间(默认是15 秒)后,还是没有可用的Connection则 就会出现上面的错误。

  • 连接池问题案例及解决:

前几天同事问我一个问题,一种CS架构的程序,直接把SQL Server作为服务端,每个客户端直接连接数据库操作(kay注:S2的cs项目就是这种架构),如果客户端打开的数量过多时SQL Server的连接数将会特别高,数据库端形成性能瓶颈,这种情况下怎么办?想了想,造成这种情况的原因是ADO.NET的内部机制造成的。ADO.NET中为了提高性能,所以使用了连接池,这样每个请求就不必都创建一个连接,然后认证,然后执行SQL,而是从连接池中直接取出连接执行SQL,执行完成后也并不是真正关闭连接,而是将该连接重新放回连接池中。如果有100个客户端,每个客户端在使用一段时间后连接池中保存了10个连接,那么在这种情况下,即使不在客户端做任何操作,SQL Server上都有1000个连接,这样不出性能问题才怪。

既然是连接池的问题,那么我就针对该问题想到了2个解决办法:

1.关闭ADO.NET的连接池,每次执行SQL时都是新建一个连接执行,然后关闭。这样做将使数据查询有所减慢(每次都建立连接,每次都认证,当然会慢了),不过这个慢是毫秒级的,一般感觉不到的,但是如果一个操作就涉及到几百个SQL语句的情况可能会明细感觉到减慢。修改方法特别简单,都不用修改代码,在数据库链接字符串中加入Pooling=False;即可。

2.修改架构,这种CS架构除了性能问题外还会出现其他的比如安全上的问题。可以将直接连数据库的方法改成连接服务,这其中可以使用Remoting、Web服务等,当然现在可以统一用WCF了。这样做就只有服务程序去连接数据库,而客户端只连接服务程序,这样就不会出现连接池造成的瓶颈。不过这样做代码修改量很大,若真要改还是很痛苦的。

原文地址:https://www.cnblogs.com/gougou1981/p/12217261.html

时间: 2024-10-12 18:31:28

Ado.net中SQLServer数据库连接池的相关文章

一次项目实践中DBCP数据库连接池性能优化

关于数据库连接池DBCP的关注源于刚刚结束的一轮测试,测试内容是衡量某Webserver服务创建用户接口的性能.这是一款典型的tomcat应用,使用的测试工具是Grinder.DBCP作为tomcat服务器常用的数据库连接池,其性能表现直接关乎应用的性能. 1.遇到的问题 当并发量增加到100时,该接口出现瓶颈,此时TPS接近400,如下图.但是服务端CPU和内存等资源并未达到瓶颈,服务器CPU使用率仅为30%,内存使用率为40%.监控到的javaMethod慢方法为incrAppAccount

3中建立数据库连接池dbcp和c3p0和tomcat数据池

DBCP数据源:需要 •Commons-dbcp.jar:连接池的实现 •Commons-pool.jar:连接池实现的依赖库 dbcpconfig.properties(这个在src同目录下--模板) #连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbc username=root password= #<!-- 初始化连接 --> initialSize=10 #最大连接数量 max

关于SQLSERVER数据库连接池

页内导航 1.如何开启连接池? 2. 那连接池是和什么有关呢? 3.如何使用相同的连接池访问不同的数据库? 4.数据库连接池的默认最大和最小值 ‘关于数据库连接池大家都听说过或者用过,但真正的了解有多少呢? 数据连接池如何启用?有哪些主要的参数? 为什么要使用连接池? 如何关闭连接池? 如何在不开启新的连接池情况下切换当前数据库? 连接池的生命周期? 当数据库服务器强制关闭连接时会怎么样? =====================================================

【java servlet】在java servlet中配置数据库连接池的配置(在server.xml)

<Context path="/" docBase="" debug="0"> <!-- name:给出数据源设置名字: auth:表示该数据源是由谁管理:type:表示类型--> <Resource name="zhaoyan" auth="Container" type="javax.sql.DataSource"/> <ResourcePa

Asp.Net中SqlServer数据库连接方式

本人应届生,每次搞研发连接数据库的时候都要把之前的连接代码拷贝过来或者从网上搜索,很是麻烦,可又有心无心的记不住它,于是写下来 当然,我们一般用的最多的当属SqlServer 身份验证,<add name="conn" connectionString="Data Source=.;Initial Catalog=dbName;Persist Security Info=True;User ID=sa;Password=;MultipleActiveResultSets

C# ADO.net 数据库连接池

前一阵开发一套系统,同组的同事提供了一个数据库连接组件,是他自己封装的,使用了自定义的连接池,用着很是不爽,而且经常会因为程序不严谨的原因,导致连接池里的连接被用完,也导致其他错误,因此我想自己研究一下ado.net 的连接池. 其实很早以前,我就接触过连接池,只是从来没有实际使用过,在我的印象里,一个连接池应该是跟SqlConnection,MySqlConnection等差不多,都是实现了IDBConnection 接口,这样程序在使用的时候,是没有任何代码入侵,只是在new 一个conne

javaweb学习总结(三十九)——数据库连接池

一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.拓机.如下图所示: 二.使用数据库连接池优化程序性能 2.1.数据库连接池的基本概念 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性

数据库连接池proxool的两种使用方式

数据库连接池可以通过两种方式来应用,针对web应用和非web应用而来. 非web应用的数据库连接池配置 第一种方式:工厂类 非web应用可以使用工厂模式将数据库连接创建封装在一个工具类中,工具类中又使用单例模式来创建加载驱动,代码如下: 工厂类:ConnectPoolFactory.java 1 import java.io.InputStream; 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import j

数据库连接池之Proxool使用

如果想要搭建一个高效的网站,链接池是必须用到的一部分.而连接池的选择是多种多样的.就现在的软件开发界而言,最为多用的是DBCP, c3p0, 和 proxool.而hibernate推荐使用的是c3p0 和proxool,并且宣布不再支持DBCP. 因此,重点就是如果想要在自己的应用程序中加入数据库连接池,就必须掌握其中的一种,而最好得选择就是c3p0和proxool中的任何一种. 下面来说说数据库连接池的相关概念和基本原理,以便于读者更加容易的理解后边的实际应用. 使用过数据库操作的人都知道,