このトピックでは、ドライバーが接続プール サービスを提供する方法に関する情報を含む 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
SQLError や SQLSetConnectOption などの非推奨の関数は、ドライバー対応の接続プールではサポートされていません。
プール 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を受け入れるように、次の関数を変更する必要があります。
ドライバー マネージャーは、複数のスレッドが同じSQL_HANDLE_DBC_INFO_TOKENハンドルを同時に使用しないことを保証します。 したがって、このハンドルの同期モデルは、ドライバー内で非常に単純なことができます。 ドライバー マネージャーは、SQL_HANDLE_DBC_INFO_TOKENを割り当てて解放する前に環境ロックを取得しません。
ドライバー マネージャーの SQLAllocHandle と SQLFreeHandle は、この新しいハンドルの種類を受け入れません。
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 の場合も同様です。
状態図
この状態図は、このトピックで説明する接続情報トークン オブジェクトを示しています。 この図は SQLDriverConnect のみを示していますが、SQLConnect の場合も同様です。 ドライバー マネージャーは、いつでもエラーを処理する必要があるため、ドライバー マネージャーは、任意の状態の SQLFreeHandle を呼び出すことができます。