在 ODBC 驱动程序中开发连接池意识

本主题讨论开发 ODBC 驱动程序的详细信息,其中包含驱动程序应如何提供连接池服务的信息。

启用驱动程序感知连接池

驱动程序必须实现以下 ODBC 服务提供程序接口(SPI)函数:

  • SQLSetConnectAttrForDbcInfo

  • SQLSetConnectInfo

  • SQLSetDriverConnectInfo

  • SQLGetPoolID

  • SQLRateConnection

  • SQLPoolConnect

  • SQLCleanupConnectionPoolID

有关详细信息 ,请参阅 ODBC 服务提供程序接口 (SPI) 参考

启用驱动程序感知池化,驱动程序还必须实现以下现有函数:

功能 新增功能
SQLAllocHandle

SQLFreeHandle

SQLGetDiagField

SQLGetDiagRec
支持新的句柄类型:SQL_HANDLE_DBC_INFO_TOKEN(请参阅以下说明)。
SQLSetConnectAttr 支持新的仅能设置的连接属性:SQL_ATTR_DBC_INFO_TOKEN 以重置连接(请参阅以下说明)。

注释

识别驱动程序的连接池不支持已弃用的函数,例如 SQLErrorSQLSetConnectOption

池标识

池 ID 是一个指针长度的驱动程序特定标识符,用于表示可以互换使用的特定连接组。 给定一组连接信息后,驱动程序应能够快速推断相应的池 ID。

例如,池 ID 应对服务器名称和凭据信息进行编码。 但是,不需要数据库名称,因为驱动程序可能能够重复使用连接,然后比建立新连接更短的时间更改数据库。

驱动程序应定义一组将构成池 ID 的键属性。 这些键属性的值可能来自连接属性、连接字符串和 DSN。 如果这些源中存在任何冲突,则应使用现有的特定于驱动程序的解决策略来向后兼容。

驱动程序管理器将根据不同的池 ID 使用不同的池。 同一池中的所有连接都是可重用的。 驱动程序管理器永远不会重复使用具有不同池 ID 的连接。

因此,驱动程序应为其定义的键属性中具有相同值的每个连接组分配唯一的池 ID。 如果驱动程序对键属性中具有不同值的两个连接使用相同的池 ID,驱动程序管理器仍将将它们放入同一池(驱动程序管理器对特定于驱动程序的键属性一无所知)。 这意味着驱动程序需要向驱动程序管理器报告,具有一组不同关键属性的连接在 SQLRateConnection 函数中不可重用。 这可以减少性能,不建议这样做。

即使所有连接信息都匹配,驱动程序管理器也不会重复使用从另一个驱动程序环境分配的连接。 即使连接具有相同的池 ID,驱动程序管理器也会对不同的环境使用不同的池。 因此,池 ID 是其驱动程序环境的本地 ID。

用于从驱动程序获取池 ID 的函数是 SQLGetPoolID 函数

连接分级

与建立新连接相比,可以通过在共用连接中重置某些连接信息(例如 DATABASE)来获得更好的性能。 因此,你可能不希望数据库名称位于密钥属性集中。 否则,可以为每个数据库创建单独的池,但这在中间层应用中可能不太理想,因为客户使用各种不同的连接字符串。

每当重复使用具有某些属性不匹配的连接时,应根据新的应用程序请求重置不匹配的属性,以便返回的连接与应用程序请求相同(请参阅 SQLSetConnectAttr 函数中属性SQL_ATTR_DBC_INFO_TOKEN的讨论)。 但是,重置这些属性可能会降低性能。 例如,重置数据库需要对服务器进行网络调用。 因此,如果连接可用,则重复使用完全匹配的连接。

驱动程序中的分级函数可以使用新的连接请求评估现有连接。 例如,驱动程序的分级函数可以确定:

  • 如果现有连接与请求完全匹配。

  • 如果只有一些微不足道的不匹配(例如连接超时),则不需要与服务器通信来重置。

  • 如果存在一些不匹配的属性,这些属性需要与服务器通信以重置,但仍会导致比建立新连接更好的性能。

  • 如果某属性的重置过程非常耗时,并且在该属性上出现不匹配的情况,驱动程序的开发人员可以考虑将此属性添加到用于生成池 ID 的关键属性集。

0 到 100 之间的分数是可能的,其中 0 表示不重复使用,100 表示完全匹配。 SQLRateConnection 是用于对连接进行评分的函数。

新建 ODBC 句柄 - SQL_HANDLE_DBC_INFO_TOKEN

为了支持驱动程序感知连接池,驱动程序需要连接信息来计算池 ID。 驱动程序还需要连接信息来比较新的连接请求与池中的连接。 每当池中没有任何连接可以重复使用时,驱动程序必须建立一个新的连接,因此需要连接信息。

由于连接信息可能来自多个源(连接字符串、连接属性和 DSN),因此驱动程序可能需要分析连接字符串并解决上述每个函数调用中这些源之间的冲突。

因此,引入了新的 ODBC 句柄:SQL_HANDLE_DBC_INFO_TOKEN。 使用SQL_HANDLE_DBC_INFO_TOKEN时,驱动程序无需多次分析连接字符串并解决连接信息中的冲突。 由于这是特定于驱动程序的数据结构,因此驱动程序可以存储连接信息或池 ID 等数据。

此句柄仅用于驱动程序管理器和驱动程序之间的接口。 应用程序无法直接分配此句柄资源。

此句柄的父句柄的类型为 SQL_HANDLE_ENV,这意味着驱动程序可以在连接信息解析期间从 HENV 句柄获取环境信息。

每当收到新的连接请求时,驱动程序管理器都会在确认驱动程序支持连接池感知后,分配SQL_HANDLE_DBC_INFO_TOKEN类型的句柄来存储连接信息。 使用完句柄之后(但在从 SQLDriverConnectSQLConnect 返回除 SQL_STILL_EXECUTING 之外的某些返回代码之前),驱动程序管理器将释放该句柄。 因此,句柄在 SQLAllocHandle 调用后被创建,并在 SQLFreeHandle 调用后被销毁。 驱动程序管理器保证在 SQLDriverConnectSQLConnect 返回错误时,先释放句柄,然后释放其关联的 HENV。

驱动程序应修改以下函数以接受新的句柄类型SQL_HANDLE_DBC_INFO_TOKEN:

  1. SQLAllocHandle

  2. SQLFreeHandle

  3. SQLGetDiagField

  4. SQLGetDiagRec

驱动程序管理器保证多个线程不会同时使用同一个SQL_HANDLE_DBC_INFO_TOKEN句柄。 因此,此句柄的同步模型在驱动程序中可能非常简单。 驱动程序管理器在分配和释放SQL_HANDLE_DBC_INFO_TOKEN之前不会获取环境锁。

驱动程序管理器的 SQLAllocHandleSQLFreeHandle 不接受此新句柄类型。

SQL_HANDLE_DBC_INFO_TOKEN可能包含机密信息,例如凭据。 因此,驱动程序应在使用 SQLFreeHandle 释放此句柄之前安全地清除包含敏感信息的内存缓冲区(使用 SecureZeroMemory)。 每当应用程序的环境句柄关闭时,所有关联的连接池都将关闭。

驱动程序管理器连接池分级算法

本部分讨论驱动程序管理器连接池的分级算法。 驱动程序开发人员可以实现相同的算法以实现向后兼容性。 此算法可能不是最好的算法。 应根据实现优化此算法(否则,没有理由实现此功能)。

驱动程序管理器将为池中的每个连接返回一个从 0 到 100 的整型评级。 0 表示无法重复使用连接,100 表示完全匹配。 假设连接请求名为 hRequest,并且池中的现有连接命名为 hCandidate。 如果以下任一条件为 false,则无法为 hRequest 重复使用共用连接 hCandidate(驱动程序管理器将分配评级为 0)。

  • hCandidate 和 hRequest 都来自 UNICODE API(如 SQLDriverConnectW)或 ANSI API(如 SQLDriverConnectA)。 (鉴于 ANSI API 和 UNICODE API(请参阅连接属性SQL_ATTR_ANSI_APP),UNICODE 驱动程序的行为可能有所不同。

  • hCandidate 和 hRequest 由同一函数创建;SQLDriverConnect 或 SQLConnect。

  • 使用 SQLDriverConnect 时,用于打开 hCandidate 的连接字符串应与 hRequest 相同。

  • 使用 SQLConnect 时,用于打开 hCandidate 的 ServerName(或 DSN)、用户名和密码应与用于打开 hRequest 的相同。

  • 当前线程的安全标识符(SID)应与用于打开 hCandidate 的 SID 相同。

  • 对于登记和非登记成本高昂的驱动程序(请参阅 SQLConnect 中SQL_DTC_TRANSITION_COST的讨论),重用 hRequest 不得需要额外的登记或取消登记。

下表显示了不同方案的分数分配。

对共用连接与请求之间的连接属性的比较 无登记/取消登记 需要额外的登记/取消登记
目录(SQL_ATTR_CURRENT_CATALOG)不同 60 50
某些连接属性不同,但目录相同 90 70
所有连接属性完全匹配 100 80

序列图

此序列图显示了本主题中所述的基本池机制。 它仅显示 SQLDriverConnect 的使用,但 SQLConnect 情况类似。

序列图

状态图

此状态图显示了本主题中所述的连接信息令牌对象。 此关系图仅显示 SQLDriverConnect ,但 SQLConnect 情况类似。 由于驱动程序管理器可能需要随时处理错误,因此驱动程序管理器可以调用 SQLFreeHandle 以获取任何状态。

状态图

另请参阅

识别驱动程序的连接池
ODBC 服务提供程序接口 (SPI) 参考