连接和池

概述

.NET 的神通数据提供程序通过连接字符串(包含用户名和密码等信息)创建安全套接字连接到数据库.

连接到远程数据源可能需要很长时间. 为了最大程度地降低网络打开连接的成本, 神通数据库.NET 驱动使用一种称为“连接池”的优化技术, 这种技术可最大程度地降低重复打开和关闭连接所造成的成本.

控制创建一个池化的连接或者未池化的连接是通过连接字符串中的 POOLING 关键词去区分设置, 如果要创建一个未池化的连接, 则必须在连接字符串中加入 POOLING=FALSE;, 例如连接字符串 Server=10.1.203.25;Port=2003;User Id=SYSDBA;Password=szoscar55;Database=OSRDB;POOLING=FALSE;; 否则驱动自动设置 POOLING=TRUE, 即创建一个池化的连接.

连接

打开一个与后台数据库的连接,取得一个 OscarConnection 类的实例,这个实例就在应用程序和后台数据中建立了一个连接,使用这个连接,我们就能操作数据库了.
要得到 OscarConnection 的实例,参数是一个连接字符串,连接字符串需要输入用户名、密码等等.
连接字符串的格式是使用分号分隔的键/值参数对列表:
keyword1=value1;keyword2=value2;keywordn=valuen;
关键字不区分大小写
代码示例
// 创建池化连接
OscarConnection connect = new OscarConnection("Server=10.1.203.25;Port=2003;User Id=SYSDBA;Password=szoscar55;Database=OSRDB;");
// 创建池化连接
// OscarConnection connect = new OscarConnection("Server=10.1.203.25;Port=2003;User Id=SYSDBA;Password=szoscar55;Database=OSRDB;POOLING=TRUE;");
// 创建未池化连接
// OscarConnection connect = new OscarConnection("Server=10.1.203.25;Port=2003;User Id=SYSDBA;Password=szoscar55;Database=OSRDB;POOLING=FALSE;");
connect.Open();    // 打开

...
connect.Dispose(); // 释放
注意 OscarConnection 继承 IDisposable, 使用之后注意及时释放.

连接池

连接到远程数据源可能需要很长时间. 为了最大程度地降低网络打开连接的成本, 神通数据库.NET驱动使用一种称为“连接池”的优化技术, 这种技术可最大程度地降低重复打开和关闭连接所造成的成本.

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

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

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

只有配置相同的连接可以建立同一个池连接,不同连接配置同时保留多个池, 每个配置一个池. 连接按照连接字符串标识分到多个池中,还根据连接是否已在事务中登记来建立池连接.

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

OscarConnection 对象的 ConnectionString 属性支持连接字符串键/值对, 可以用于调整连接池逻辑的行为, 例如连接字符串 POOLING=TRUE (默认) 控制开启连接池功能, 反之 POOLING=FALSE. 有关详细信息, 请参阅 连接字符串.

池的创建和分配

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

在以下 C# 示例中创建了三个新的 OscarConnection 对象, 但是管理时只需要两个连接池. 注意, 根据为 Database 分配的值, 第一个和第二个连接字符串有所不同.
using (var connection = new OscarConnection("Server=10.1.1.66;Port=2003;UserId=SYSDBA;Password=szoscar55;Database=OSRDB1;"))
{
    connection.Open();
    // The connection string matches pool 1.
}
using (var connection = new OscarConnection("Server=10.1.1.66;Port=2003;UserId=SYSDBA;Password=szoscar55;Database=OSRDB2;"))
{
    connection.Open();
    // The connection string matches pool 2.
}
using (var connection = new OscarConnection("Server=10.1.1.66;Port=2003;UserId=SYSDBA;Password=szoscar55;Database=OSRDB1;"))
{
    connection.Open();
    // The connection string matches pool 1.
}
如果 MINPOOLSIZE 在连接字符串中未指定或指定为零, 池中的连接将在一段时间不活动后关闭. 但是, 如果指定的 MINPOOLSIZE 大于零, 在 AppDomain 被卸载并且进程结束之前, 连接池不会被破坏. 非活动或空池的维护只需要最少的系统开销.
当出现故障转移等错误时, 会自动清除池.
添加连接

连接池是为每个唯一的连接字符串创建的. 当创建一个池后, 将创建多个连接对象并将其添加到该池中, 以满足最小池大小的需求. 连接根据需要添加到池中, 但是不能超过指定的最大池大小(默认值为 1000),为保持最小连接池数 MINPOOLSIZE 数据库连接池最小连接数(1 默认),用户可以自定义稳定的连接池数量. 连接在关闭或断开时释放回池中.

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

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

释放
我们强烈建议您在使用完连接时一定要释放连接, 以便连接可以返回池. 要释放连接, 可以使用 Connection 对象的 Close 或 Dispose 方法, 也可以通过在 C# 的 using 语句中打开所有连接, 不是显式关闭的连接可能不会添加或返回到池中.
移除连接

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

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

清除池

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