`
北极的。鱼
  • 浏览: 158939 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】C#-ADO.Net连接池和连接字符串剖析

阅读更多

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

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

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

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

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


池的创建和分配

在 初次打开连接时,将根据完全匹配算法创建连接池,该算法将池与连接中的连接字符串关联。 每个连接池都与一个不同的连接字符串相关联。 打开新连接时,如果连接字符串并非与现有池完全匹配,将创建一个新池。 按进程、按应用程序域、按连接字符串以及(在使用集成的安全性时)按 Windows 标识来建立池连接。 连接字符串还必须是完全匹配的;按不同顺序为同一连接提供的关键字将分到单独的池中。

在以下 C# 示例中创建了三个新的 SqlConnection 对象,但是管理时只需要两个连接池。 注意,根据为 Initial Catalog 分配的值,第一个和第二个连接字符串有所不同。

 

using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=Northwind"))
{
    connection.Open();
    // Pool A is created.
}

using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=pubs"))
{
   connection.Open();
   // Pool B is created because the connection strings differ.
}

using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=Northwind"))
{
   connection.Open();
   // The connection string matches pool A.
}

 

如 果 MinPoolSize 在连接字符串中未指定或指定为零,池中的连接将在一段时间不活动后关闭。 但是,如果指定的 MinPoolSize 大于零,在 AppDomain 被卸载并且进程结束之前,连接池不会被破坏。 非活动或空池的维护只需要最少的系统开销。

注意:

当出现故障转移等错误时,会自动清除池。

添加连接

连接池是为每个唯一的连接字符串创建的。 当创建一个池后,将创建多个连接对象并将其添加到该池中,以满足最小池大小的要求。 连接根据需要添加到池中,但是不能超过指定的最大池大小(默认值为 100)。 连接在关闭或断开时释放回池中。

在请求 SqlConnection 对象时,如果存在可用的连接,将从池中获取该对象。 连接要可用,必须未使用,具有匹配的事务上下文或未与任何事务上下文关联,并且具有与服务器的有效链接。

连接池进程通过在连接释放回池中时重新分配连接,来满足这些连接请求。 如果已达到最大池大小且不存在可用的连接,则该请求将会排队。 然后,池进程尝试重新建立任何连接,直到到达超时时间(默认值为 15 秒)。 如果池进程在连接超时之前无法满足请求,将引发异常。

警告:
我们强烈建议您在使用完连接后总是将其关闭,以使连接返回到池中。要关闭连接,可以使用 Connection 对象的 CloseDispose 方法,也可以通过在 C# 的 using 语句中或在 Visual Basic 的 Using 语句中打开所有连接。 不是显式关闭的连接可能不会添加或返回到池中。

移除连接

如果连接长时间空闲,或池进程检测到与服务器的连接已断开,连接池进程会将该连接从池中移除。 注意,只有在尝试与服务器进行通信之后才能检测到断开的连接。 如果发现某连接不再连接到服务器,则会将其标记为无效。 无效连接只有在关闭或重新建立后,才会从连接池中移除。

如 果存在与已消失的服务器的连接,那么即使连接池管理程序未检测到已断开的连接并将其标记为无效,仍有可能将此连接从池中取出。 这种情况是因为检查连接是否仍有效的系统开销将造成与服务器的另一次往返,从而抵消了池进程的优势。 发生此情况时,初次尝试使用该连接将检测连接是否曾断开,并引发异常。

清除池

ADO.NET 2.0 引入了清除池的两种新方法: ClearAllPools 和 ClearPool。 ClearAllPools 清除给定提供程序的连接池,ClearPool 清除与特定连接关联的连接池。 如果在调用时连接正在使用,将进行相应的标记。 连接关闭时,将被丢弃,而不是返回池中。

使用连接字符串关键字控制连接池

下表列出了 ConnectionString 内连接池值的有效名称。有关更多信息,请参见 SQL Server 连接池 (ADO.NET)。

Connection Lifetime

0

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

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

Connection Reset

'true'

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

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

Enlist

'true'

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

Load Balance Timeout

0

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

Max Pool Size

100

池中允许的最大连接数。

Min Pool Size

0

池中允许的最小连接数。

Pooling

'true'

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

从深蓝居的博客上找到的描述:

前几天同事问我一个问题,一种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了。 这样做就只有服务程序去连接数据库,而客户端只连接服务程序,这样就不会出现连接池造成的瓶颈。不过这样做代码修改量很大,若真要改还是很痛苦的。

以下是网上找到的一篇介绍ADO.NET连接池的文章,感觉不错。

连接池允许应用程序从连接池中获得一个连接并使用这个连接,而不需要为每一个连接请求重新建立一个连接。一旦一个新的连接被创建并且放置在连接池中,应用程序就可以重复使用这个连接而不必实施整个数据库连接创建过程。

当应用程序请求一个连接时,连接池为该应用程序分配一个连接而不是重新建立一个连接;当应用程序使用完连接后,该连接被归还给连接池而不是直接释放。

如何实现连接池

确保你每一次的连接使用相同的连接字符串(和连接池相同);只有连接字符串相同时连接池才会工作。如果连接字符串不相同,应用程序就不会使用连接池而是创建一个新的连接。

优点

使 用连接池的最主要的优点是性能。创建一个新的数据库连接所耗费的时间主要取决于网络的速度以及应用程序和数据库服务器的(网络)距离,而且这个过程通常是 一个很耗时的过程。而采用数据库连接池后,数据库连接请求可以直接通过连接池满足而不需要为该请求重新连接、认证到数据库服务器,这样就节省了时间。

缺点

数据库连接池中可能存在着多个没有被使用的连接一直连接着数据库(这意味着资源的浪费)。

技巧和提示

1. 当你需要数据库连接时才去创建连接池,而不是提前建立。一旦你使用完连接立即关闭它,不要等到垃圾收集器来处理它。

2. 在关闭数据库连接前确保关闭了所有用户定义的事务。

3. 不要关闭数据库中所有的连接,至少保证连接池中有一个连接可用。如果内存和其他资源是你必须首先考虑的问题,可以关闭所有的连接,然后在下一个请求到来时创建连接池。

连接池FAQ

1. 何时创建连接池?

当第一个连接请求到来时创建连接池;连接池的建立由数据库连接的连接字符创来决定。每一个连接池都与一个不同的连接字符串相关。当一个新的连接请求到来时如果连接字符串和连接池使用的字符串相同,就从连接池取出一个连接;如果不相同,就新建一个连接池。

2. 何时关闭连接池?

当连接池中的所有连接都已经关闭时关闭连接池。

3. 当连接池中的连接都已经用完,而有新的连接请求到来时会发生什么?

当连接池已经达到它的最大连接数目时,有新的连接请求到来时,新的连接请求将放置到连接队列中。当有连接释放给连接池时,连接池将新释放的连接分配给在队列中排队的连接请求。你可以调用close和dispose将连接归还给连接池。

4. 我应该如何允许连接池?

对于.NET应用程序而言,默认为允许连接池。(这意味着你可以不必为这件事情做任何的事情)当然,如果你可以在SQLConnection对象的连接字符串中加进Pooling=true;确保你的应用程序允许连接池的使用。

5. 我应该如何禁止连接池?

ADO.NET默认为允许数据库连接池,如果你希望禁止连接池,可以使用如下的方式:

1) 使用SQLConnection对象时,往连接字符串加入如下内容:Pooling=False;

2) 使用OLEDBConnection对象时,往连接字符串加入如下内容:OLE DB Services=-4;

 

 

通过上面的两篇文章希望大家可以明白什么是数据库连接池,什么时候适用,什么时候不适用。关于性能测试,我做了一个小例子,大家可以看看:

第一次运行:



 多次运行后:

 



 

测试按钮的代码如下:

 

string connStringUsePool = "server=.;database=pubs;uid=sa;pwd=123456;pooling=true;connection lifetime=0;min pool size = 1;max pool size=50";
string connStringUnUsePool = "server=.;database=pubs;uid=sa;pwd=123456;pooling=false";

private void button1_Click(object sender, EventArgs e)
{


    int count = 50;

    DateTime start = DateTime.Now;
    for (int i = 0; i < count; i++)
    {
        using (SqlConnection conn = new SqlConnection(connStringUsePool))
        {
            conn.Open();
            conn.Close();
        }
    }
    DateTime end = DateTime.Now;
    TimeSpan ts = end - start;
    label1.Text = "使用连接池" + ts.Milliseconds.ToString();

    start = DateTime.Now;
    for (int i = 0; i < count; i++)
    {
        using (SqlConnection conn = new SqlConnection(connStringUnUsePool))
        {
            conn.Open();
            conn.Close();
        }
    }
    end = DateTime.Now;
    ts = end - start;
    label2.Text = "不使用连接池" + ts.Milliseconds.ToString();
}

 

  • 大小: 24 KB
  • 大小: 29.2 KB
分享到:
评论

相关推荐

    ado.net 连接数据库封装

    在给定的代码片段中,可以看到多个`using`语句,这些语句引入了ADO.NET相关的命名空间,比如`System.Data.SqlClient`用于与SQL Server数据库交互,而`System.Configuration`则用来读取配置文件中的连接字符串。...

    ADO.net 2.0 认证最新版

    10. 在C#代码中,两个SqlConnection对象虽然连接字符串相似,但由于它们是独立创建的,因此会创建两个不同的连接池来管理这两个对象。 11. SQL错误号4060表示连接字符串指定的服务器名称无效,导致无法打开连接。 ...

    ADO.NET选择题及答案

    - 上述代码中的两个连接字符串虽然参数顺序不同,但内容相同,因此会被视为不同的连接,从而创建两个连接池。 #### 题目11:打开SQLConnection时返回的SQL Server错误号为4060,该错误表示: **选项:** - **A. ...

    ADO.NET题库(共206题)

    - 当使用相同的连接字符串创建多个`SqlConnection`对象时,它们会被放入同一个连接池中,但如果连接字符串中有任何不同之处,则会创建新的连接池。 **例题解析** &gt; 10参考下列C#语句: &gt; &gt; ```csharp &gt; ...

    ADO.NET 2.0技术内幕(高清 中文 带书签 全)

    构建连接字符串,启用连接池;执行查询,包括参数化查询和非同步查询,并获取结果;创建DataSet对象以处理脱机数据,并研究常用场景;使用Microsoft SQL Server 2005中新的公共语言运行时特性和XML数据类型;为简单...

    ADO.Net详解,Net数据库操作,Vb.Net数据库编程

    - **3.9.1 对存储池数据库连接采用相同连接字符串**:这种做法可以减少资源消耗。 - **3.9.2 运行SQL Server分析器来检验SQL和RPC查询**:SQL Server分析器可以识别潜在的问题。 - **3.9.3 避免添加运行时...

    商业编程-源码-Asp.net简单多选投票系统.zip

    9. **部署与配置**:最后,系统需要能够部署到IIS服务器,配置如数据库连接字符串、应用程序池设置等。 通过分析这个Asp.NET投票系统源码,开发者不仅可以了解Asp.NET的基本架构,还能深入学习到Web应用的开发流程...

    供求信息网-ASP.NET

    在实际运行环境中,"供求信息网"需要配置正确的连接字符串、应用程序池和权限设置。 10. **调试与优化** ASP.NET提供了一系列的开发和调试工具,如Visual Studio,可以帮助开发者快速定位和解决问题。同时,通过...

    ADO.NET开发最佳实践---vs2003

    可以使用`using`语句块来确保连接在使用完毕后自动关闭,或者使用连接池以复用已存在的连接,减少创建和销毁连接的开销。 2. **数据适配器和数据集**:数据适配器(DataAdapter)是ADO.NET中的关键组件,它负责在...

    MAC_数据库访问技术-ADO[1].NET程序设计模拟题

    **解析:** 在上述代码示例中,虽然两个SqlConnection对象都使用了相同的连接字符串,但由于它们的构造顺序不同,因此.NET Framework将创建两个独立的连接池来管理这些连接对象。这是因为连接池管理器会基于连接字符...

    ADO。net 认证题库

    以上就是ADO.NET认证题库中涉及的关键知识点,包括ADO.NET对象模型、数据访问、XML支持、身份验证机制、数据提供程序以及连接池的使用等。理解并掌握这些内容对于进行ADO.NET编程和解决实际问题至关重要。

    AdoNetConnectionExam

    在ASP.NET应用中,使用ADO.NET连接到这样的数据库文件时,需要配置正确的连接字符串,指定数据库的路径和身份验证信息。 3. **TPDataSource**:这可能是一个数据源控件的配置文件,通常用于ASP.NET中的数据绑定。...

    C# ajax和数据库连接池小实例

    2. .NET Framework中的数据库连接池:在C#中,ADO.NET提供了内置的数据库连接池。例如,使用SqlConnection类连接SQL Server时,系统会自动管理连接池。 3. 连接池的优点:减少创建和销毁连接的开销,提高并发性能,...

    实例88-ADO数据库.rar

    本实例“实例88-ADO数据库”显然聚焦于如何利用ADO技术来操作数据库,可能是通过编程语言如VBScript、VBA或者.NET语言如C#、VB.NET等实现的。下面将详细阐述ADO的主要组成部分、功能以及如何使用它来访问和操作...

    计算机毕业设计-ASP.NET学生信息管理系统(源代码+LW).zip

    8. **部署与配置**:项目部署涉及IIS服务器配置、数据库连接字符串设置、应用程序池选择等,确保系统在服务器上稳定运行。 9. **错误处理与日志记录**:良好的系统应包含异常处理和日志记录机制,方便排查问题和...

    C#,ASP.NET 校友录源码

    10. **部署和配置**:项目的部署可能需要IIS服务器,还需要配置应用程序池、数据库连接字符串等。 通过学习和分析这个校友录源码,初学者不仅可以掌握C#和ASP.NET的基础,还能了解到Web开发的完整流程,包括前端...

    mysql.data.dll-6.9.8 包含.net 2.0 4.0 4.5

    MySQL.Data.dll 是 MySQL 数据库与 .NET 应用程序交互的核心组件,主要负责提供 ADO.NET 接口,使得 .NET 开发者可以方便地在 C#、VB.NET 等语言中操作 MySQL 数据库。版本 6.9.8 意味着这是一个更新的版本,可能...

    C#源代码-ConnectionPoolDemoTest.zip

    在本压缩包"C#源代码-...通过分析和学习"ConnectionPoolDemoTest"项目,你可以深入理解C#如何与数据库进行交互,以及如何利用连接池来提升性能。此外,注释的存在使得学习过程更为直观和简单,帮助初学者快速上手。

    C#数据库系统软件开发.pdf

    - 属性:ConnectionString、ConnectionTimeOut、Database、DataSource、ServerVersion和State,分别用于设置连接字符串、超时时间、当前数据库、服务器信息、版本和连接状态。 - 方法:Open()和Close()用于打开和...

    c#.net+sql server2000写的留言板

    【标题】:“C#.NET+...这个“C#.NET+SQL Server 2000写的留言板”项目为初学者提供了一个了解和实践Web应用开发的良好起点,通过学习和分析源代码,可以加深对C#.NET和数据库编程的理解,同时提升实际项目开发能力。

Global site tag (gtag.js) - Google Analytics