您现在的位置:龙卷风首页 ›› 网络编程 ›› 阅读文章

asp.net连接池和SqlConnection对象的释放

ADO.NET 连接池问题当你的网站访问量达到一定规模时就会凸现。

原文出处:http://www.cnblogs.com/rickie/archive/2004/10/02/48546.aspx

原文标题:关于ADO.Net连接池(Connection Pool)的一些个人见解

一下是原文:

建立池连接可以显著提高应用程序的性能和可缩放性。SQL Server .NET Framework 数据提供程序自动为 ADO.NET 客户端应用程序提供连接池(MSDN)。

Opening a database connection is a resource intensive and time consuming operation. Connection pooling increases the performance of Web/windows applications by reusing active database connections instead of creating a new connection with every request. Connection pool manager maintains a pool of open database connections. When a new connection requests come in, the pool manager checks if the pool contains any unused connections and returns one if available. If all connections currently in the pool are busy and the maximum pool size has not been reached, the new connection is created and added to the pool. When the pool reaches its maximum size all new connection requests are being queued up until a connection in the pool becomes available or the connection attempt times out.

Connection pooling behavior is controlled by the connection string parameters. Please look into MSDN documents in the reference link if you want to know further information.

 

前面是关于连接池知识的一些基本介绍,下面的内容是重点,也是个人见解。因为没有这方面的文档资料参考或者佐证,所以请各位仔细思考和讨论(我不想误导大家)。

下面分2种情况进行讨论。

1,Client端的windows form application通过ADO.Net直接访问后台Database。

  

SqlServer DirectConnection

我认为在这种情况下,每一个Client端和Database之间都存在一个连接池。通过设置ConnectiongString的Max Pool Size和Min Pool Size属性来验证。

如Max Pool Size = 5, Min Pool Size = 3, 通过SQL Server的SP_WHO2可以检测导如下结果:

启动1个Client端的Windows form application:application和SQL Server之间存在3个connection。

启动2个Client端的Windows form application:application和SQL Server之间存在6个connection。

启动3个Client端的Windows form application:application和SQL Server之间存在9个connection。

 

由此可见,每一个Client端和SQL Server之间都存在一个连接池,否则9个connection已经超出了Max Pool Size的设定。

 

2,Client端的application不直接通过ADO.Net来访问后台Database,而是通过IIS Server来同后台Database Server打交道。

至少有如下2种情况:

(1)Client通过IE访问部署在IIS中的web application,web application中的Data Access Class进一步访问后台Database Server.

(2)Client端的windows form application访问部署在IIS中的Remote Object,Remote Object进一步访问后台Database Server.

  

SqlServer InDirectConnection 

下面进行同样的测试:通过设置ConnectiongString的Max Pool Size和Min Pool Size属性来验证。

如Max Pool Size = 5, Min Pool Size = 3, 通过SQL Server的SP_WHO2可以检测导如下结果:

启动1个Client端的Web form application:application和SQL Server之间存在3个connection。

启动2个Client端的Web form application:application和SQL Server之间存在3个connection。

启动3个Client端的Web form application:application和SQL Server之间存在3个connection。

调用由IIS承载的Remote Object,结果类似。只是在未启动Client端之前,发现在Remote Object与Database Server之间已经存在一个connection。

由此可见,对同一个application而言,IIS Server与Database Server之间只有存在一个连接池,与Client端的多少没有关系。

3,连接池小节

根据上面的测试结果,显然第二种情况更有利于减少无用的连接数量,提高Database Server的性能。关于.Net Remoting技术及其性能问题,可以参考如下的Reference连接,这里就不讨论了。

另外,本文是个人关于连接池的一些见解,如果观点有不正确之处,希望不要误导各位。欢迎各位在此发表意见。同意的说赞同,不同意的请提出您的看法。谢谢。

Reference Links:

(1) MSDN, ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconconnectionpoolingforsqlservernetdataprovider.htm

(2) Microsoft .NET Remoting:技术概述, http://www.microsoft.com/china/MSDN/library/NetFramework/default.mspx

(3) 性能比较:.NET Remoting 与 ASP.NET Web 服务, http://www.microsoft.com/china/msdn/archives/library/dnbda/html/bdadotnetarch14.asp

========================原文结束,开可以参考另外一篇文章:NET 连接池救生员
原文的一些补充观点:

连接的创建和获取:

Q: 如果我最大连接池是5个,那么,在我的程序中,每次访问,我都会使用New一个连接,然后Open,使用以后,然后Close,那么在每次New的时候,会不会创建连接,?
A: 在每次New的时候,如果connection pool中有空闲的连接,则不会创建新连接,否则会创建。 

如果超过最多连接数,还能发出New的请求,但是该请求会放入队列,直到connection pool中有空闲连接或连接请求超时。

连接的效率问题:

Q: 要是可以对连接进行控制的话,应该怎么控制,很简单,我现在每次使用数据库访问时,都会New并close,我是担心这样的效率是不是会很低啊,想在连接上提高效率,要怎么操作呢? 

A: 使用connection pool时,New并不一定会创建新的连接,如果connection pool中有空闲连接,直接拿来就用。

close也只是将连接放入connection pool,供后续请求使用。因此不会有效率问题。

连接的存活时间:

当连接返回到池中时,将对它的创建时间和当前时间进行比较,如果时间间隔超过由 Connection Lifetime 指定的值(以秒为单位),则会毁坏该连接。在聚集配置中可以使用它来强制在运行服务器和刚联机的服务器之间达到负载平衡。
如果值为零 (0),则将使池连接具有最大的超时期限。默认值为0

SqlConnection.Close和.Dispose的比较:

sqlconnection.close和.dispose的相同地方是:
dispose肯定调用了close,所以close里面有做的事情,dispose都包括 

dispose还做了其他的资源的释放,这样在GC第一次回收的时候,省却了dispose的步骤,加快了内存资源的回收速度。
如果没有调用dispose,GC将在第一次回收先做dispose。

如果程序频繁做new sqlconnection(),然后很快就做close并且不再使用这个connection(例如一些com+/asp.net/web service的程序),而且又不做dispose,那么随着这个程序被多次调用,被分配但未能尽快释放的系统资源(通常是内存)会有很多,GC被迫回收的次数也相应增多,系统的整体效率就会变低(GC回收的时候是所有.net程序都暂停,等GC回收跑完才可以继续,造成其他程序也受到影响)。所以对于这种情况,做dispose好。
但如果其他情况,例如Winforms的client,那么没有所谓。

最近发现本站有时候会出现连接不上服务器的现象,通过sp_who查看数据库连接时,发现网站应用程序占用了比较多的连接数,当连接数达到一定数量后,网站就会出现连接不上数据库的错误。那么可以肯定,网站出现错误的原因,是数据库连接没有及时释放的缘故——或者是开辟了太多的连接。网站的数据库访问逻辑没有集中在一个数据库访问类中,而是在用到的时候建立,用完了关闭。那么这种情况是否跟上文讲的第一种情况相同呢?上文的第一种情况应该是针对winform应用程序来说的。但是本站的程序没有想上文说的第二种情况,把数据访问集中在一个数据访问类中。这个问题有待实践来验证。

作者 不见不散 本文仅代表作者观点,与龙卷风资讯网立场无关。

我来说两句

内容/Content