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) をサポートします (以下の説明を参照)。

Note

SQLErrorSQLSetConnectOption などの非推奨の関数は、ドライバー対応の接続プールではサポートされていません。

プール ID

プール ID は、同じ意味で使用できる接続の特定のグループを表すポインター長のドライバー固有の ID です。 接続情報のセットを指定すると、ドライバーは対応するプール ID をすばやく推測できる必要があります。

たとえば、プール ID は、サーバー名と資格情報をエンコードする必要があります。 ただし、ドライバーが接続を再利用し、新しい接続を作成するよりも短い時間でデータベースを変更できる可能性があるため、データベース名は必要ありません。

ドライバーは、プール ID を構成する一連のキー属性を定義する必要があります。 これらのキー属性の値は、接続属性、接続文字列、および DSN から取得できます。 これらのソースに競合がある場合は、下位互換性のために既存のドライバー固有の解決ポリシーを使用する必要があります。

ドライバー マネージャーは、プール ID ごとに異なるプールを使用します。 同じプール内のすべての接続は再利用可能です。 ドライバー マネージャーは、別のプール ID を持つ接続を再利用することはありません。

そのため、ドライバーは、定義されたキー属性で同じ値を持つ接続のすべてのグループに一意のプール ID を割り当てる必要があります。 ドライバーがキー属性に異なる値を持つ 2 つの接続に同じプール ID を使用する場合、ドライバー マネージャーは引き続きそれらを同じプールに配置します (ドライバー マネージャーはドライバー固有のキー属性について何も認識しません)。 つまり、ドライバーは、別のキー属性のセットを持つ接続が SQLRateConnection 関数内で再利用可能ではないことをドライバー マネージャーに報告する必要があります。 これによりパフォーマンスが低下する可能性があり、これは推奨されません。

ドライバー マネージャーは、すべての接続情報が一致する場合でも、別のドライバー環境から割り当てられた接続を再利用しません。 ドライバー マネージャーは、接続に同じプール 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の種類のハンドルを割り当てます。 ハンドルの使用が完了すると (ただし、SQLDriverConnect または SQLConnect からSQL_STILL_EXECUTING以外のリターン コードを返す前に)、ドライバー マネージャーはハンドルを解放します。 そのため、ハンドルは SQLAllocHandle 呼び出しの後に作成され、SQLFreeHandle 呼び出しの後に破棄されます。 ドライバー マネージャーは、関連付けられている HENV を解放する前にハンドルが解放されることを保証します (SQLDriverConnect またはSQLConnect がエラーを返す場合)。

ドライバーは、新しいハンドルの種類の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 の場合、プールされた接続 hCandidate を hRequest に再利用できません (ドライバー マネージャーは評価 0 を割り当てます)。

  • hCandidate と hRequest はどちらも UNICODE API (SQLDriverConnectW など) または ANSI API (SQLDriverConnectA など) から取得されます。 (UNICODE ドライバーは、特定の ANSI API と UNICODE API によって動作が異なる場合があります (接続属性のSQL_ATTR_ANSI_APPを参照)。)

  • hCandidate と hRequest は同じ関数によって作成されます。SQLDriverConnect または SQLConnect。

  • SQLDriverConnect を使用する場合、hCandidate を開くために使用される接続文字列は hRequest と同じである必要があります。

  • hCandidate を開くために使用する ServerName (または DSN)、ユーザー名、パスワードは、SQLConnect を使用するときに hRequest を開くために使用するのと同じにする必要があります。

  • 現在のスレッドのセキュリティ識別子 (SID) は、hCandidate を開くために使用される SID と同じである必要があります。

  • 参加と登録解除にコストがかかるドライバーの場合 (SQLConnect でのSQL_DTC_TRANSITION_COSTの説明を参照)、hRequest を再利用するには、追加の参加または登録解除を必要としてはなりません。

次の表は、さまざまなシナリオでのスコアの割り当てを示しています。

プールされた接続と要求の間の接続属性の比較 参加なし/登録解除 追加の参加/登録解除が必要
カタログ (SQL_ATTR_CURRENT_CATALOG) が異なる 60 50
一部の接続属性は異なりますが、カタログは同じです 90 70
すべての接続属性が完全に一致 100 80

シーケンス図

このシーケンス図は、このトピックで説明する基本的なプーリング メカニズムを示しています。 SQLDriverConnect の使用のみを示していますが、SQLConnect の場合も同様です。

Sequence Diagram

状態図

この状態図は、このトピックで説明する接続情報トークン オブジェクトを示しています。 この図は SQLDriverConnect のみを示していますが、SQLConnect の場合も同様です。 ドライバー マネージャーは、いつでもエラーを処理する必要があるため、ドライバー マネージャーは、任意の状態の SQLFreeHandle を呼び出すことができます。

State Diagram

参照

ドライバー対応接続プール
ODBC サービス プロバイダー インターフェイス (SPI) リファレンス