2

バックグラウンド

Oracleデータベースに接続するWCFサービスを使用するC#/VB.netクライアントアプリケーションがあります。Webサービスは、.NET FrameworkのOracle用データプロバイダーを使用してデータベースに接続します(ODPと混同しないでください)。私たちのテスターは、散発的なOracleアカウントのロックを経験しました。これは、ユーザーのOracleパスワードを変更した直後に発生するようです。dba_audit_trailログは、ユーザーまたはクライアントのアクティビティなしで、非常に定期的な間隔(つまり、ドット上で2分ごと)での自動接続試行のように見えるものを明らかにしました。多数のログ(IIS、WCFトレース、メッセージログなど)により、これらの接続の試行がクライアントアプリケーションによって直接開始されていないことが確認されています。これらは、Webサービスから独立して、またはSystem.Data.OracleClientライブラリ内から提供されている必要があります。

場合によっては、これらの自動試行はパスワードが変更される前に開始され、データベースに正常に接続されますが、パスワードが変更されるとすぐに、無効なユーザー名/パスワードに対して次の試行が失敗します。3回試行すると、アカウントがロックされます。これらの定期的な接続試行のソースを見つけようとしています。

オラクルのフォーラムで、非常によく似た、しかし答えのない問題を見つけまし

現在の考え

最新の調査により、接続プールによる予期しない動作であると考えられました。パスワードを変更する前にユーザーがWebサービスに接続した場合、元の接続文字列に対して接続プールが作成されます。パスワードを変更してWebサービスに再度ログインした後、データプロバイダーは新しい接続文字列に基づいて新しい接続プールを作成します。

データプロバイダー内の何かが、最初の接続プールから古い接続を維持しようとしている可能性がありますか?おそらく、最初の接続プールは古い接続を破棄し、新しい接続を(現在は無効な接続文字列で)補充しようとしています。何が原因でしょうか?注:最小/最大プールサイズ(0/100)のデフォルト設定を使用しています。

コードが最初の接続プールからの接続に直接アクセスしようとしているとは思われません。ユーザーのセッションには前のセッションのパスワードのメモリがないため、最初の接続プールを参照するために古い接続文字列を使用することはありません。さらに、私たちのコードには、私たちが見ている非常に正確な接続間隔を説明するものは何もありません。

4

3 に答える 3

3

根本的な問題は、解放されていないデータベース接続であることになりました。接続が開かれると、接続プールからチェックアウトされます。接続が閉じられない場合、プールは接続がまだ使用されていると見なします。これにより、プール管理ロジックは、元の接続文字列を使用してデータベースで定期的に再認証されます。パスワードが変更されると、ログイン試行の失敗とアカウントのロックにすぐにつながります。

// Problem logic; connection is never closed/returned to the connection pool.
public static void ConnPoolTest1()
{
    OracleConnection conn = new OracleConnection(connectionStringWithPooling);
    conn.Open();

    //...Do some work

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail.
    Console.ReadKey(); // Since connection was never released back to the connection pool, the
                       // data provider's pool management will regularly re-authenticate with DB.
                       // If user's password changes before this process dies (releasing the
                       // connection pools), you start accumulating failed password attempts.
}

この問題の適切な修正は、接続が終了したときに接続が常にプールに返されるようにすることです。

// Best practice: ALWAYS CLOSE YOUR CONNECTIONS WHEN YOU ARE DONE!
public static void ConnPoolTest2()
{
    OracleConnection conn = new OracleConnection(connectionStringWithPooling);
    conn.Open();

    //...Do some work

    conn.Close();

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail.
    Console.ReadKey(); // No problem here! No recurring authentication attempts because the
                       // connection has been returned to the pool.
}

注:他の回答では、パスワードが変更されたときにプールをオフにし、古い接続プールをクリアすることを提案しました。これらの提案は、リリースされていないリソースを検索する際の一時的なパッチとして機能し、問題を特定するのに大いに役立ちました。

于 2012-10-15T21:50:41.033 に答える
2

これは少し役立つかもしれません。

OracleODP.Netと接続プール

OLE DB、ODBC、およびOracle接続プール

基本的に、MSDNの2番目のWebページには、「作成されると、アクティブなプロセスが終了するまで接続プールは破棄されません」と記載されています。Webサービスが非常に多くの接続/接続プールを保持しているため、問題が発生しているようです。

だから私の提案:接続のログ(おそらくテキストファイル)を追加してもう少しトラブルシューティングを行うか、最初のリンクにデータベースへの接続を追跡するための優れたコマンドがあるほか、接続プールをオフにしてみます今のところ。あなたが抱えていると思われる問題は「プールの断片化」と呼ばれています。これは、接続プールを介してすべてのデータベース接続をパイプしている単一のコンピューターへのトラフィックが多い場所です。非常に多くのプールが存在するため、メモリの問題が発生し始め、接続が適切に閉じられません。接続が閉じられていない場合、または古い接続プールを使用した他のコマンドのリストの前にパスワード変更コマンドが実行された場合、問題が発生します。

最終的に、あなたの状況では、独自のWeb接続プール(ユーザー用ではない)を作成し、独自の接続を介してデータをユーザーに提供する単一のポイント(Webサービス)があります。つまり、接続しているユーザーに対処するには、Webサービス側で処理されるさまざまなタイプの認証が必要になるということです。今のところ、モデルの変更は多すぎると思いますが、最終的にはその解決策を見つけることを強くお勧めします。

于 2012-10-14T13:10:10.107 に答える
2

接続を無効にするイベントが発生した場合は常に、プールを破棄して、リークされた接続やプールのキープアライブに適切なマークを付けて、再利用を防ぐ必要があります。このためには、データプロバイダーのclearpoolorメソッドを使用する必要があります。clearallpools

http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracleconnection.clearpool.aspx

さらに、グローバル例外マネージャーは、無効なユーザーに対してスローされた例外をリッスンし、接続文字列の一部として識別されたユーザーの接続を列挙することにより、そのプールを破棄できます。おそらく効率的ではありませんが、仕事を成し遂げる必要があります。

于 2012-10-15T06:23:17.593 に答える