代码改变世界

Connection pool

2011-07-31 15:39  一一九九  阅读(1346)  评论(0编辑  收藏  举报

wikipedia中的解释:

        在软件工程中connection pool 是对database connections 的cache,   主要作用是重用对已经建立的数据库请求,提升数据库执行命令的效率。为每一个用户打开和维护一个数据库连接,尤其是对数据驱动的网站来说,成本是非常高并且很浪费资源的。在connection pool 中,当一个连接被创建时就被放到了Pool中,当一个新的请求到达时这个连接可以被重复使用,假如Pool中的所有连接都处于使用的状态,当新的连接请求到达的时候就会创建新的连接并且被放到pool中。连接池也降低了用户等待和数据库建立连接的时间

Applications

      connetion pool通常由web-based或enterprise application 的application server来进行管理和维护。 当任何动态的网页打开一个数据库连接的时候,得到的连接是由被application server管理的conneciton pool返回的,当任何动态的网页关闭一个数据库连接的时候,是将这个链接返回到connection pool中。

      connection Pool并不仅仅限于使用application server的应用程序。传统的处理需要频繁的访问数据库的Application也能从中受益。这些application经常手动的维护database connections, 这些操作通常需要良好的程序设计,并且框架是十分复杂的。在过去的几年中,得益于第三方的类库比如说connction pool 或者Sql STATEMENT POOL, 使得依赖于数据库的程序的性能提高很高。

     为了使connection pool 在应用中获取较好的效果,需要根据需要设置最小连接数、最大连接数以及空闲连接数。

Database support

     支持连接池的数据库有 ms sqlserver , orcale ,mysql , postgresql.

wikipedia中解释并不完全正确,至少没有解释为什么建立一个连接是如此的慢。可以看一下MSDN中的解释。在MSDN的使用连接池中解释的比较清楚。

使用连接池(from msdn)

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

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

       连接池减少了新连接需要打开的次数。池进程保持物理连接的所有权。通过为每个给定的连接配置保留一组活动连接来管理连接。

       只有配置相同的连接可以建立池连接。ADO.net同时保留多个池,每个配置一个池。连接由连接字符串以及 Windows 标识(在使用集成的安全性时)分为多个池。

连接池和数据提供程序(from msdn)

  • Ole DB.net FrameWork 数据提供程序连接池。 使用OLE DB会话池自动管理连接池。
  • ODBC.net Framework 数据提供程序的连接池
  • Oracle.net Framework 数据提供程序连接池。

池的管理(from msdn)

  • 池的创建和分配。 当连接打开时,将根据一种精确的匹配算法来创建连接池,该算法会使连接池与连接中的字符串相关联。每个连接池都与一个不同的连接字符串相关联。当新连接打开时,如果连接字符串不精确匹配现有池,则将创建一个新池。连接池一旦创建,直到活动进程终止时才会被销毁。维护部活动的池或者空池占用的资源非常少。
  • 连接池的添加。连接池是为每个唯一的连接字符串创建的。当创建一个池后,将创建多个连接对象并将多个连接对象并将其添加到该池中,以满足最小池大小的要求。连接将根据需要添加池中,直至达到最大池大小。
  • 连接的移除。 如果连接长时间空闲,或池进程检测到与服务器的连接已断开,连接池进程会将该连接从池中移除。请注意,只有在尝试与服务器进行通信后,才能检测到这种情况。如果发现某连接不再连接到服务器,则会将其标记为无效。连接池管理程序会定期扫描连接池,查找已释放到池中并标记为无效的对象。找到后,这些连接将被永久移除。 如果存在一个与已经消失的服务器的连接,如果连接池进场尚未检测到断开的连接并将连接标记为无效,可以从池中提取此连接。当发生这种情况时,将生成异常。但是,为了将该连接释放到池中,仍需要将其关闭。 不要在类的finalize方法中对Connection、datereader或者任何其他托管对象调用close或者dispose.在终结器中,仅释放类直接拥有的非托管资源。如果类不拥有任何非托管资源,则不要在类定义中包含finalize方法。
  • 事务支持。连接是根据事务上下文来从池中取出来并且进行分配的。请求线程和所分的连接的上下文必须匹配。因此,每个连接池实际上又分为不具有关联事务上下文的连接以及N个各自包含于一个特定事务上下文的连接的子部分。当连接关闭时,它将被释放回池中,并根据其事务上下文放入相应的子部分。因此,及时分布式事务仍然挂起,仍可以关闭连接而不会生成错误。可以随后提交或者终止分布式事务。

池的使用

      池的监控。计算机管理中添加计数器,如下图所示:

image

(一)池的作用:
         执行以下代码:Connection默认的连接数目是100.

for(int i=0; i< 50; i++)
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=Ordering"))
{
    connection.Open();
    // Pool A is created.
}

显示的计数器大体如下所示,可以看到技术器的数目始终都是1,说明在重复使用连接:

image

(二)执行以下代码,OpenConnection并不关闭,此时Connection被占用了。

for (int i = 0; i < 50; i++)
{
    SqlConnection connection = new SqlConnection(
      "Integrated Security=SSPI;Initial Catalog=Ordering");
    connection.Open();
 
}

此时的计数器显示如下图,可以看到Connection一直被占用着。

image

将上述的代码生成的Exe,同时打开,此时Connction并没有倍增,但是仍然增加了,所以说Conneciton和进程仍然存在一定关系的。如下图所示:

image

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

参考资料:
         http://en.wikipedia.org/wiki/Connection_pool
        http://msdn.microsoft.com/zh-cn/library/ms254502%28v=vs.80%29.aspx
        http://msdn.microsoft.com/zh-cn/library/8xx3tyca%28v=vs.80%29.aspx
        http://www.cnblogs.com/idior/archive/2006/09/08/499128.html