web-dev-qa-db-ja.com

Oracleが断続的に「ORA-12516、TNS:リスナーはプロトコルスタックが一致する使用可能なハンドラーを見つけられませんでした」をスローします

Oracle XE接続確立メカニズムをテストしているときに、次の問題にぶつかりました。接続は各反復で閉じられますが、50〜100接続後、Oracleは断続的に次の例外をスローし始めます。

Java.sql.SQLException: Listener refused the connection with the following error:
ORA-12516, TNS:listener could not find available handler with matching protocol stack

    at Oracle.jdbc.driver.T4CConnection.logon(T4CConnection.Java:489) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.Java:553) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.Java:254) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.Java:32) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.driver.OracleDriver.connect(OracleDriver.Java:528) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.Java:280) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.Java:207) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at Oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.Java:157) ~[ojdbc6-11.2.0.4.jar:11.2.0.4.0]
    at com.vladmihalcea.book.high_performance_Java_persistence.jdbc.connection.OracleConnectionCallTest.test(OracleConnectionCallTest.Java:57) [test-classes/:na]

テストは次の場所にあります GitHub

for (int i = 0; i < callCount; i++) {
    try {
        long startNanos = System.nanoTime();
        try (Connection connection = dataSource.getConnection()) {
        }
        timer.update(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
        sleep(waitMillis);
    } catch (SQLException e) {
        LOGGER.info("Exception on iteration " + i, e);
    }
}

35ミリ秒の待機ステップで接続を開閉しようとすると、すべて正常に動作します。待機時間を10 msに下げると、timからtimeに例外がスローされ始めます。

考えられる理由の1つは、この記事で説明できます。 http://www-01.ibm.com/support/docview.wss?uid=swg21603472

TNS-12516またはTNS-12519エラーが報告される最も一般的な理由の1つは、PROCESSESおよび/またはSESSIONS制限の設定された最大数に達していることです。これが発生すると、TNSリスナーのサービスハンドラーが「ブロック」され、新しい接続を確立できなくなります。 TNSリスナーが、データベースインスタンスに関連付けられたPMONプロセスから更新を受信して​​TNSリスナーに通知すると、しきい値は設定された制限を下回り、データベースは接続の再開を受け入れます。

  • PMONは、ロードやディスパッチャー情報などの特定のインスタンスに関する情報でリスナーを更新する責任があります。専用接続の最大負荷は、PROCESSESパラメータによって決定されます。 PMONがSERVICE_UPDATE情報を提供する頻度は、インスタンスのワークロードによって異なります。これらのサービス更新の最大間隔は10分です。
  • リスナーは、インスタンスに対して確立した接続の数をカウントしますが、終了した接続に関する情報をすぐには取得しません。 PMONがSERVICE_UPDATEを介してリスナーを更新する場合のみ、リスナーに現在の負荷が通知されます。これには10分ほどかかる場合があるため、リスナーに応じた現在のインスタンスの負荷と実際のインスタンスの負荷には差が生じる可能性があります。

現在の接続数が最大負荷に達したとリスナーが判断すると、インスタンスのサービスハンドラーの状態を「ブロック」に設定し、次のエラーのいずれかで着信クライアント接続を拒否し始める可能性があります:ora-12519またはora-1251 」

これがなんらかのバグなのか、それとも単にOracleがどのように機能するように設計されているのかだけ知りたいのです。

更新

Oracle 11g Enterprise Editionでは問題なく動作するため、XEの制限があります。

修正

接続プールの使用 はおそらくこの問題を修正する最良の方法であり、これにより接続取得時間とレベルアップトラフィックスパイクも削減されます。

6
Vlad Mihalcea

バグではありません。この動作は予期されたものです。接続を増やす必要がある場合は、プロセス制限を変更するだけです。

SQL> show parameter processes
processes                            integer     150

SQL> alter system set processes = <integer> scope=[...];
SQL> shutdown immediate;
SQL> startup;

-pfileまたはspfileを使用する場合、プロセスパラメータは静的であるため、dbをバウンスする必要があります。

また、完全を期すために、本番環境でプロセスの制限を増やす必要がある場合は、トランザクションやセッション(プロセスから派生)などの相関パラメータも増やす必要があるかもしれません。 v $ resource_limitをクエリして、使用中の現在の制限と値を確認できます。

SQL> select * from v$resource_limit where resource_name in ('processes', 'sessions', 'transactions');
8