この付録では、Java Database Connectivity(JDBC)アプリケーションまたはアプレットのトラブルシューティングについて説明します。内容は次のとおりです。
この項では、Oracle JDBCドライバの使用中に発生する可能性のある、一般的な問題について説明します。たとえば、次の問題があります。
PL/SQLでは、CHAR
またはVARCHAR2
列がOUT
またはIN/OUT
変数として定義される場合、ドライバは32512文字のCHAR
配列を割り当てます。このため、メモリー消費に関する問題が生じます。JDBC Thinドライバは、VARCHAR2
出力型を使用する場合、メモリーを割り当てません。ただし、JDBC OCIドライバは、CHAR
とVARCHAR2
の両方の型に対してメモリーを割り当てます。このため、OCIドライバのCPU負荷はThinドライバより高くなります。
以前のリリースでは、この問題はStatement.setMaxFieldSize
メソッドをコールすることで解決できました。これよりもよい解決方法は、OracleCallableStatement.registerOutParameter
を使用することです。すべてのCHAR
またはVARCHAR2
列で、必ずregisterOutParameter(int paramIndex, int sqlType, int scale, int maxLength)
をコールすることをお薦めします。このメソッドは、oracle.jdbc.driver.OracleCallableStatement
に定義されています。4つ目の引数maxLength
を使用して、メモリー消費を制限します。このパラメータは、この列の格納に必要な文字数をドライバに指示します。文字配列に列データを保持できない場合、列は切り捨てられます。3つ目の引数scale
は、ドライバでは無視されます。
カーソルまたはメモリーが不足しているというメッセージを受け取った場合は、すべてのStatement
およびResultSet
オブジェクトを明示的にクローズしてください。Oracle JDBCドライバには、ファイナライザ・メソッドがありません。クリーン・アップ・ルーチンは、ResultSet
およびStatement
クラスのclose
メソッドで実行されます。結果セットおよび文オブジェクトを明示的にクローズしておかないと、重大なメモリー・リークが発生します。また、データベースのカーソルが不足します。文をクローズすると、データベース内の対応するカーソルが解放されます。
同様に、サーバー側でのリークおよびカーソル不足を避けるには、Connection
オブジェクトも明示的にクローズしておく必要があります。接続をクローズすると、その接続に関連付けられたオープン中の文オブジェクトが、JDBCドライバによってクローズされ、サーバー側のカーソルが解放されます。
JDBCドライバでは、PL/SQLストアド・プロシージャにBOOLEAN
パラメータを渡せません。PL/SQLプロシージャにBOOLEAN
値が含まれている場合、そのPL/SQLプロシージャを、引数をINT
として受け取る2番目のPL/SQLプロシージャでラップし、最初のストアド・プロシージャに渡します。2番目のプロシージャがコールされると、サーバーによってINT
からBOOLEAN
に変換されます。
ストアド・プロシージャの例を示します。BOOLPROC
は、BOOLEAN
パラメータを渡そうとします。2番目のプロシージャBOOLWRAP
は、BOOLEAN
値とINT
値の置換えを実行します。
CREATE OR REPLACE PROCEDURE boolproc(x boolean)
AS
BEGIN
[...]
END;
CREATE OR REPLACE PROCEDURE boolwrap(x int)
AS
BEGIN
IF (x=1) THEN
boolproc(TRUE);
ELSE
boolproc(FALSE);
END IF;
END;
// Create the database connection from a DataSource
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:oci:@<...hoststring...>");
ods.setUser("scott");
ods.setPassword("tiger");
Connection conn = ods.getConnection();
CallableStatement cs = conn.prepareCall ("begin boolwrap(?); end;");
cs.setInt(1, 1);
cs.execute ();
必ずしも1プロセスで約17以上のJDBC-OCI接続をオープンできないことがあります。サーバー上のプロセス数が初期化ファイルに指定されている制限を超えたためか、またはプロセスごとのファイル記述子の制限を超えた可能性があります。1つのJDBC-OCI接続で、複数のファイル記述子が使用される(3から4個のファイル記述子が使用されます)ことがあります。
サーバーで17以上のプロセスを使用可能にしている場合は、プロセスごとのファイル記述子の制限が原因である可能性があります。この制限数を増やすと、解決する可能性があります。
JDBC標準メソッドStatement.cancel
は、データベースにメッセージを送信することにより、SQL文の実行を正常に停止させます。データベースは、これに応答して実行を停止し、エラー・メッセージを返します。Statement.execute
をコールしたJavaスレッドはサーバーで待機し、他のスレッドからのStatement.cancel
コールにより呼び出された返答のエラー・メッセージを受信した場合にのみ実行を続けます。
このため、Statement.cancel
は、ネットワークとデータベースが正しく機能していることに依存します。ネットワーク接続が切断するか、データベース・サーバーがダウンした場合、クライアントは取消しメッセージに対するエラー応答を受け取りません。サーバー・プロセスに障害が発生すると、多くの場合、JDBCはStatement.execute
をコールしたスレッドを解放するIOException
を受け取ります。ただし、サーバーがダウンしてもJDBCがIOException
を受け取らない場合があります。Statement.execute
を開始したスレッドは、Statement.cancel
によって解放されません。
JDBCがIOException
を受け取らない場合は、Oracle Netがいずれはタイムアウトし、接続をクローズすることになります。これにより、IOException
が発生し、スレッドが解放されます。ただし、このプロセスにはかなりの時間がかかることがあります。このタイムアウトを制御する方法は、OracleDatasource.setConnectionProperties()
のreadTimeout
プロパティの説明を参照してください。このタイムアウトは、Oracle Netの設定を使用してチューニングすることもできます。詳細は、『Oracle Database Net Services管理者ガイド』を参照してください。
JDBC標準メソッドStatement.setQueryTimeout
は、Statement.cancel
に依存します。指定されたタイムアウト間隔よりも実行時間が長くなった場合、モニター・スレッドがStatement.cancel
をコールします。これは、前述と同じすべての制限を受けます。この結果、Statement.execute
をコールしたスレッドがタイムアウトにより解放されない場合があります。
実行と取消しの間の時間の長さは、それほど正確ではありません。この間隔は、指定されたタイムアウト間隔より短くはなりませんが、数秒間長くなることがあります。アプリケーションに、高い優先順位で実行されているアクティブ・スレッドがある場合、この間隔は随意に長くなることがあります。モニター・スレッドは高い優先順位で実行されますが、他にも高い優先順位のスレッドがあり、それが実行し続けられる場合があります。モニター・スレッドが開始されるのは、ゼロ以外のタイムアウトで実行される文がある場合のみです。すべてのOracle JDBC文の実行を監視するモニター・スレッドは、1つのみあります。
Statement.cancel
とStatement.setQueryTimeout
は、サーバー側内部ドライバでサポートされません。サーバー側内部ドライバは単一スレッドのサーバー・プロセスで動作します。Oracle JVMはこの単一スレッド・プロセス内にJavaスレッドを実装します。サーバー側内部ドライバがSQL文を実行している場合、JavaスレッドはStatement.cancel
をコールできません。これは、Oracle JDBC監視スレッドにも適用されます。
アイドル接続に対するファイアウォール・タイムアウトによって、接続が切断される場合があります。このために、JDBCアプリケーションが接続の待機中に停止する可能性があります。ファイアウォール・タイムアウトによって接続が切断されないようにするには、次の処理を1つ以上実行します。
接続キャッシュまたは接続プーリングを使用している場合は、接続キャッシュのInactivityタイムアウト値を、常にファイアウォールのアイドル・タイムアウト値より短い値に設定します。
接続プロパティとしてoracle.net.READ_TIMEOUT
を渡してソケット上で読込みタイムアウトを有効にします。タイムアウト値はミリ秒で指定します。
JDBC OCIドライバとJDBC Thinドライバの両方について、ネット記述子を使用してデータベースに接続し、接続記述子のDESCRIPTION
句にENABLE=BROKEN
パラメータを指定します。また、TCP_KEEPALIVE_INTERVAL
の下限値も設定します。
サーバー側のsqlnet.ora
ファイルにSQLNET.EXPIRE_TIME=1
を設定して、Oracle Net DCDを使用可能にします。
ネットワークの信頼性が低い場合、サーバーの接続が突然切断されても、クライアントでは頻繁に発生する切断を検出するのが困難です。デフォルトでは、Linux上で稼働するクライアントは、突然の切断を検出するのに7200秒(2時間)かかります。この値は、tcp_keepalive_time
プロパティの値と同じです。アプリケーションが切断をより迅速に検出するようにするには、tcp_keepalive_time
、tcp_keepalive_interval
およびtcp_keepalive_probes
プロパティの値をオペレーティング・システム・レベルでより小さい値に設定する必要があります。
注意: tcp_keepalive_interval プロパティに小さい値を設定すると、ネットワーク上にプローブ・パケットが頻繁に送出され、システム速度が低下する可能性があります。そのため、このプロパティの値は、システム要件に基づいて適切に設定してください。 |
また、接続記述子のDESCRIPTION
句にENABLE=BROKEN
パラメータを指定する必要があります。たとえば、次のようになります。
jdbc:oracle:thin:@(DESCRIPTION=(ENABLE=BROKEN)(ADDRESS=(PROTOCOL=tcp)(PORT=1521)(HOST=myhost))(CONNECT_DATA=(SID=orcl)))
デバッグに役立つスタック・トレースの出力など、SQL例外の処理については、「SQL例外の処理」を参照してください。
クライアントおよびサーバーのOracle-Netトレースが、Oracle Net経由で送信されるパケットをトラップできるようにできます。クライアント側トレースはJDBC OCIドライバについてのみ使用できます。JDBC Thinドライバについてはサポートされません。トレースとトレース・ファイルの読取りに関する詳細な情報は、Oracle Net Services管理者ガイドを参照してください。
トレース機能を使用すると、ネットワーク・イベントが実行されるたびにそのイベントについて記述される、一連の詳細な文が生成されます。操作をトレースすることにより、イベントの内部操作に関する詳細な情報を取り出すことができます。この情報は読込み可能ファイルに出力され、エラーの原因となったイベントを特定できます。トレース情報の収集は、SQLNET.ORA
ファイルにあるいくつかのOracle Netパラメータによって制御されます。SQLNET.ORA
のパラメータを設定した後に、トレースを実行するために新しい接続を作成する必要があります。
トレース・レベルを高くすると、より詳細な情報がトレース・ファイルに取得されます。トレース・ファイルの理解が難しくなるため、トレースを有効にする場合はトレース・レベル4から開始します。トレース・ファイルの最初の部分は接続ハンドシェイク情報です。JDBCプログラムに関連するSQL文とエラー・メッセージの情報は、その先を参照してください。
注意: トレース機能ではディスク領域が大量に使用されるため、システムのパフォーマンスが大幅に低下する可能性があります。トレースは、必要なときにのみ使用可能にしてください。 |
クライアント・システムのSQLNET.ORA
ファイルに、次のパラメータを設定します。
目的
トレースを一定の指定レベルでオン/オフにします。
デフォルト値
0またはOFF
有効な値
0またはOFF- トレースの出力なし
4またはUSER- ユーザー・トレース情報
10またはADMIN- 管理トレース情報
16またはSUPPORT- カスタマ・サポート・トレース情報
例:
TRACE_LEVEL_CLIENT=10
目的
トレース・ファイルの書込み先ディレクトリを指定します。
デフォルト値
ORACLE_HOME
/network/trace
例:
UNIX: TRACE_DIRECTORY_CLIENT=/oracle/traces
Windows: TRACE_DIRECTORY_CLIENT=C:\ORACLE\TRACES
目的
クライアント・トレース・ファイルの名前を指定します。
デフォルト値
SQLNET.TRC
例:
TRACE_FILE_CLIENT=cli_Connection1.trc
注意: TRACE_FILE_CLIENT ファイルのために選択する名前は、TRACE_FILE_SERVER ファイルのために選択する名前と異なっている必要があります。 |
サーバー・システムのSQLNET.ORA
ファイルに次のパラメータを設定します。接続ごとに、一意のファイル名を持つ個別のファイルが生成されます。
目的
トレースを一定の指定レベルでオン/オフにします。
デフォルト値
0またはOFF
有効な値
0またはOFF
- トレースの出力なし
4またはUSER
- ユーザー・トレース情報
10またはADMIN
- 管理トレース情報
16またはSUPPORT
- カスタマ・サポート・トレース情報
例:
TRACE_LEVEL_SERVER=10
目的
トレース・ファイルの書込み先ディレクトリを指定します。
デフォルト値
ORACLE_HOME
/network/trace
例:
TRACE_DIRECTORY_SERVER=/oracle/traces