4

切断されたリモート データベースのデータベース リンクにアクセスした後、JDBC データベース接続を回復できますか? (ローカル)Oracle データベースへの単一接続を使用するアプリケーションがありますが、データベース リンクを介してリモート データベースからデータを読み取る場合があります(REMOTE_DB)。問題は、リモート データベースが何らかの理由 (ネットワーク切断) でオフラインになると、データベース リンクにアクセスした後、jdbc 接続が使用できなくなることです。次の 3 つの SQL ステートメントを実行します。

1. SELECT 1 FROM DUAL@REMOTE_DB => ok
<<Network failure>>
2. SELECT 1 FROM DUAL@REMOTE_DB => SQLException. 
3. SELECT 1 FROM DUAL => SQLException. 

ojdbc6.jarステートメント 2 および 3 で発生する JDBC ドライバーでの特定の Java 例外は次のとおりです。

    java.sql.SQLRecoverableException: No more data to read from socket
    at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1185)

この動作が「設計による」ものではないと思う理由は、SQLPlusorを使用して同じシーケンスを実行しても同じ問題が発生しないためPerl DBIです。この問題は、いくつかのバージョンの Oracle シン JDBC ドライバーを使用する Oracle 11 で発生します。次の Java プログラムを使用して、問題を再現できます。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class TestJdbc {
    private static Connection connect() throws Exception {
        String jdbcURL = "jdbc:oracle:thin:@localhost:1521:TNSNAME";
        String user = "scott" ;
        String passwd ="tiger";

        Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
        return DriverManager.getConnection(jdbcURL,user,passwd);
    }

    public static void main(String[] args) throws Exception {
        Connection conn = connect();
        PreparedStatement stServer = conn.prepareStatement("SELECT 'server' FROM DUAL@REMOTE_DB");
        PreparedStatement stClient = conn.prepareStatement("SELECT 'client' FROM DUAL");
        ResultSet resultSet;

        try {
            stServer.execute();
            resultSet = stServer.getResultSet();
            if (resultSet.next()) {
                System.out.println("server: " + resultSet.getString(1));
            }
        } catch (SQLException e) {
            System.out.println("exception on server link: " + e);
        }
        // force network disconnect here and press enter
        BufferedReader lineOfText = new BufferedReader(new InputStreamReader(System.in));
        lineOfText.readLine();

        try {
            stServer.execute();
            resultSet = stServer.getResultSet();
            if (resultSet.next()) {
                System.out.println("server: " + resultSet.getString(1));
            }
        } catch (SQLException e) {
            //SQLRecoverableException occurs here
            System.out.println("exception on server link: " + e);
        }
        // press enter again
        lineOfText.readLine();

        try {
            stClient.execute();
            resultSet = stClient.getResultSet();
            if (resultSet.next()) {
                System.out.println("client: " + resultSet.getString(1));
            }
        } catch (SQLException e) {
            System.out.println("exception on client connection: " + e);
        }

        stServer.close();
        stClient.close();
    }

}

接続を閉じて再度開くと問題は解決しますが、エラーが発生したときにトランザクションの途中である可能性があるため、そうしないことをお勧めします。

編集:私は次のことができることに注意してくださいSQLPlus.JDBC接続プールを使用しても解決しない問題:

SQL> update my_table set ...;

1 row updated.

SQL> select * from dual@REMOTE_DB;

D
-
X

<<Network failure>>

SQL> select * from dual@REMOTE_DB;
select * from dual@REMOTE_DB
               *
ERROR at line 1:
ORA-12545: Connect failed because target host or object does not exist


SQL> update my_table set ...;

1 row updated.

SQL> commit;

Commit complete.

SQL> 
4

2 に答える 2