Oracle Database 11gではJDBCドライバが拡張され、新しい診断機能が追加されると同時に、既存の診断機能も改良されました。これらの機能を使用すると、Oracle JDBCドライバを使用するアプリケーションの問題や、ドライバ自体の問題を診断することができます。また、Oracle JDBCドライバを使用してOracle DatabaseインスタンスにアクセスするJavaアプリケーションを開発、保守するために必要な労力を低減できます。
Oracle JDBCドライバには、ユーザーがJDBCアプリケーションの問題を識別および修正することを可能にする次の診断機能が用意されています。
注意: JDBCドライバの診断機能は、標準のjava.util.logging フレームワークおよびjavax.management MBeanフレームワークに基づいています。これらの標準フレームワークについての情報はこの文書では扱いません。これらの標準フレームワークの詳細は、次を参照してください。
|
JDBCドライバのコードが実行されるときに発生するイベントの情報を記録します。イベントには、SQL例外などユーザーの目に触れるイベントも、内部JDBCメソッドの出入りなどの詳細JDBC内部イベントも含めることができます。ユーザーがこの機能を有効にすると、特定のイベントまたはすべてのイベントを記録することができます。
Oracle Database 11gより前は、JDBCドライバは、J2SE 2.0と3.0をサポートしていました。J2SEのこれらのバージョンには、java.util.logging
が含まれませんでした。このため、Oracle Database 11gより前のJDBCドライバ・リリースによって提供されるロギング機能は、java.util.logging
フレームワークと異なります。
Oracle Database 11gのJDBCドライバでは、J2SE 2.0と3.0はもうサポートされません。このため、JDBCドライバのロギング機能は、標準java.util.logging
パッケージをフル活用します。強化されたロギング・システムではログ・レベルが有効利用され、ユーザーはログ出力を関心のものに制限できます。特定のクラスの情報がより一貫して記録されるため、ログ・ファイルがわかりやすくなりました。
この機能では新しいAPIや構成ファイルは導入されません。既存の標準java.util.logging
構成ファイルに新しいパラメータが追加されたのみです。これらのパラメータはjava.util.logging
の使用に不可欠なもので、既存のパラメータと同様に使用されます。
注意: 生成されたログの内容の正確性は保証されません。ログの内容は大部分、実装の詳細に依存します。実装の細部はリリースのたびに変更されるため、ログの正確な内容もリリースごとに変更される傾向があります。 |
Javaアプリケーションのデバッグを開始する前に、JDBCロギングを有効にして、構成する必要があります。この項では、JDBCロギングを有効にして使用するために実行する必要がある手順を説明します。内容は次のとおりです。
JDBCドライバのそれぞれのバージョンに対応するいくつかのJARファイルが付属しています。最適化されたJARファイルにはロギング・コードが含まれていないため、使用時にログ出力が生成されません。ログ出力を取得するには、デバッグJARファイル(ojdbc5_g.jar
やojdbc6_g.jar
のようにファイル名に_gが付いています)を使用する必要があります。デバッグJARファイルはCLASSPATH
に含まれている必要があります。
注意: デバッグJARファイル、たとえばojdbc5_g.jar やojdbc6_g.jar がCLASSPATH 内の唯一のOracle JDBC JARファイルであることを確認してください。 |
ロギングを有効化する方法には次のようなものがあります。
Javaシステム・プロパティの設定
oracle.jdbc.Trace
システム・プロパティを設定することによってロギングを有効にできます。
java -Doracle.jdbc.Trace=true ...
システム・プロパティの設定によりグローバル・ロギングを有効にできます。ロギングがアプリケーション全体に対して有効になります。アプリケーション全体をデバッグする場合、またはアプリケーションのソース・コードを変更しないか変更できない場合は、グローバル・ロギングを使用できます。
プログラムによる有効化
ロギングをプログラム的に有効または無効にするには、次のようにします。
最初に、Diagnosability MBeanのObjectName
を取得します。ObjectName
は次のようになります。
com.oracle.jdbc:type=diagnosability,name=<loader>
loader
は、Oracle JDBCドライバをロードしたクラス・ローダー・インスタンスに基づいた一意の名前です。
注意: ドライバは、1つの仮想マシンに複数回ロードできます。したがって、それぞれ一意の名前を持つ複数のMBeanが存在することになります。 |
次のとおりにコードを作成します。
ClassLoader l = oracle.jdbc.OracleDriver.getClassLoader(); String loader = l.getName() + "@" + l.hashCode(); // compute the ObjectName javax.management.ObjectName name = new javax.management.ObjectName("com.oracle.jdbc:type=diagnosability, name="+loader); // get the MBean server javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); // find out if logging is enabled or not System.out.println("LoggingEnabled = " + mbs.getAttribute(name, "LoggingEnabled")); // enable logging mbs.setAttribute(name, new javax.management.Attribute("LoggingEnabled", true)); // disable logging mbs.setAttribute(name, new javax.management.Attribute("LoggingEnabled", false));
注意:
|
プログラムでロギングを有効および無効にすると、ログ出力の生成に必要なアプリケーションの部分を変更しやすくなります。
注意: 上のいずれかの方法を使用してロギングを有効にしても、重大なエラーの最小限のログが生成されるだけです。通常、それではあまり役に立ちません。より有用で詳細なログを生成するには、java.util.logging を構成する必要があります。 |
有用で詳細なログを生成するには、java.util.logging
を構成する必要があります。これには、構成ファイルを使用する方法と、プログラム的に行う方法があります。
JDBCをインストールすると、サンプル構成ファイル、OracleLog.properties
がdemo
ディレクトリに配置されます。そこにはjava.util.logging
の構成方法に関する基本情報や、最初に使用できるいくつかの初期設定が含まれています。このサンプル・ファイルをそのまま使用することも、ファイルを編集して使用することも、ファイルの名前を変更して使用することも、任意の名前を持つ完全に新しいファイルを作成することも可能です。
構成ファイルを使用するには、Javaランタイムにそれを認識させる必要があります。それには、システム・プロパティを設定します。たとえば、次のようになります。
java -Djava.util.logging.config.file=/jdbc/demo/OracleLog.properties.
ファイルはjava.util.logging
システムによって読み取られます。このファイルはどこに配置してもかまいません。
java.util.logging.config.file
とoracle.jdbc.Trace
は同時に使用できます。
java -Djava.util.logging.config.file=/jdbc/demo/OracleLog.properties -Doracle.jdbc.Trace=true
デフォルトのOracleLog.properties
ファイルを使用できます。希望する出力が得られる場合も、得られない場合もあります。独自の構成ファイルを作成して使用することもできます。次の手順に従ってください。
myConfig.properties
という名前のファイルを作成します。どのような名前を使用してもかまいません。
そのファイルに次の行のテキストを挿入します。
.level=SEVERE oracle.jdbc.level=INFO oracle.jdbc.handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=INFO java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
ファイルを保存します。
この構成ファイルを使用するようにシステム・プロパティを設定します。
java -Djava.util.logging.config.file=<filepath>/myConfig.properties ...
filepath
は、myConfig.properties
ファイルを保存したフォルダのパスです。
また、java.util.logging
を構成して、ログ出力をファイルにダンプすることができます。そうする場合は、構成ファイルを次のように変更します。
.level=SEVERE oracle.jdbc.level=INFO oracle.jdbc.handlers=java.util.logging.FileHandler java.util.logging.FileHandler.level=INFO java.util.logging.FileHandler.pattern=jdbc.log java.util.logging.FileHandler.count=1 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
これにより、正確に同じログ出力が生成され、現在のディレクトリにjdbc.log
という名前のファイルで保存されます。
レベル設定を変更することで、詳細度を制御することができます。定義されているレベルは、最も詳細度の低いものから最も高いものまで、次のようになります。
OFF
ロギングをオフにします。
SEVERE
SQLExceptionと内部エラーを記録します。
WARNING
SQLWarningと、好ましくないが致命的ではない内部の状況を記録します。
INFO
まれではあるが重要なイベントおよびエラーを記録します。生成されるログ・メッセージは比較的小量です。
CONFIG
実行されるSQL文字列を記録します。
FINE
すべてのパブリック・メソッドへの出入りが記録されるため、JDBC操作を詳細にトレースできます。生成されるログ・メッセージはかなり大量です。
FINER
内部メソッドのコールを記録します。
FINEST
大量の内部メソッドのコールを記録します。
ALL
詳細をすべて記録します。ロギング詳細度が最も高いレベルです。
注意: 詳細度がFINE を超えるレベルでは、非常に大量のログが生成されます。 |
上で示された例で詳細の出力量を削減するには、java.util.logging.FileHandler.level
設定をALL
からINFO
に変更します。
java.util.logging.FileHandler.level=INFO
oracle.jdbc
ログ出力のレベルを変更することは可能ですが、必要ありません。FileHandler
レベルを設定することで、ログ・ファイルにダンプされるログ・メッセージを制御できます。
レベルを設定すると、JDBCからのすべてのロギング出力が減少します。しかし、コードのある部分からの出力は大量に必要ですが、他の部分からはほとんど必要ない場合があります。そうするには、ログ出力に関する深い理解が必要です。
ログ出力は、名前で定義されたツリー構造をなしています。ルート・ログ出力の名前は「」(空の文字列)です。構成ファイルの最初の行には、.level=SEVERE
と記述されています。これは、ルート・ログ出力のレベル設定です。次の行はoracle.jdbc.level=INFO
です。これは、oracle.jdbc
という名前のログ出力のレベルを設定しています。oracle.jdbc
ログ出力は、ログ出力ツリーのメンバーです。その親はoracle
という名前です。oracle
ログ出力の親がルート・ログ出力(空の文字列)です。
ロギング・メッセージは、特定のログ出力(たとえば、oracle.jdbc
)に送信されます。メッセージがそのレベルのレベル・チェックに合格すると、メッセージは、そのレベルのハンドラ(存在する場合)と親ログ出力に渡されます。このため、ずっと見ていくと、oracle.log
に送信されるログ・メッセージはそのログ出力のレベル、INFO
に対して比較されます。レベルが同じか低い(詳細度が低い)場合、FileHandlerと親ログ出力(oracle)に送信されます。この場合も、レベルに対して確認されます。この例のような場合は、レベルが設定されていないため、親レベル(SEVERE
)が使用されます。メッセージ・レベルが同じか低い場合は、ハンドラに渡され(存在しません)、親に送信されます。この場合は、ルート・ログ出力の親です。このようなツリー構造は、出力の量を減らす役には立ちませんでした。役に立つのは、JDBCドライバがいくつかのサブ・ログ出力を使用するということです。ログ・メッセージをいずれかのサブ・ログ出力に制限すると、出力が大幅に少なくなります。Oracle JDBCドライバによって使用されるログ出力は、次のとおりです。
oracle.jdbc
oracle.jdbc.driver
oracle.jdbc.pool
oracle.jdbc.rowset
oracle.jdbc.xa
oracle.sql
注意: ドライバが使用するログ出力は、リリースによって異なることがあります。 |
oracle.sql
コンポーネントで発生していることを追跡し、残りのドライバに関する基本情報の一部を取得する場合を考えます。これは、ロギングのより複雑な使用方法です。config
ファイルのエントリを次に示します。
# # set levels # .level=SEVERE oracle.level=INFO oracle.jdbc.driver.level=INFO oracle.jdbc.pool.level=OFF oracle.jdbc.util.level=OFF oracle.sql.level=INFO # # configure handlers # oracle.handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=INFO java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
構成ファイルのそれぞれの行で行われている処理を検討します。
.level=SEVERE
ルート・ログ出力のロギング・レベルをSEVERE
に設定します。深刻な障害の場合を除き、他の、Oracleのものでないコンポーネントからのロギングを確認する必要はありません。このため、すべてのログ出力のデフォルト・レベルをSEVERE
に設定します。明示的に設定された場合を除いて、各ログ出力はレベルを親から継承します。ルート・ログ出力のレベルをSEVERE
に設定すると、あらためて設定したログ出力を除いて、他のすべてのログ出力が確実にそのレベルを継承するようにできます。
oracle.level=INFO
oracle.sql
とoracle.jdbc.driver
ログ出力の両方からログを出力します。共通の祖先はoracle
です。このため、oracle
ログ出力のレベルをINFO
に設定します。より低いレベルでは詳細度をより明示的に制御します。
oracle.jdbc.driver.level=INFO
ここでは、oracle.jdbc.driver
からのSQL実行の表示のみが必要です。このため、レベルをINFO
に設定します。これはかなり小量のレベルですが、このテストの処理内容を追跡するためには役立ちます。
oracle.jdbc.pool.level=OFF
このテストではDataSource
を使用しており、そのロギングすべてを表示する必要はありません。したがって、OFF
にします。
oracle.jdbc.util.level=OFF
oracle.jdbc.util
パッケージからのロギングを表示する必要はありません。XAまたはRowsetを使用していた場合、それもオフにします。
oracle.sql.level=INFO
oracle.sql
で発生していることを表示します。このため、レベルをINFO
に設定します。これにより、大量の詳細が出力されるのを回避しながら、パブリック・メソッドのコールについて多くの情報が得られます。
oracle.handlers=java.util.logging.ConsoleHandler
stderr
に全内容をダンプします。テストを実行する場合、stderr
をファイルにリダイレクトします。
java.util.logging.ConsoleHandler.level=INFO
System.err
であるコンソールに全内容をダンプします。この場合、ハンドラでなくログ出力でフィルタリングしています。
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
簡単でほぼ判読可能な形式を使用します。
この構成ファイルでテストを実行すると、oracle.sql
パッケージからは適度に詳細な情報を取得し、コア・ドライバ・コードからは少量の情報を取得します。他のコードからは何も取得しません。
XMLFormatter
を使用して、Oracleサポートにログを送信することもできます。
カスタムjava.util.logging.Filter
を実装および使用して、ログに書き込まれたデータをより詳細に制御できます。これは標準java.util.logging
機能で、JSEのJavaDocに記述されています。カスタム・フィルタを使用すると、次のことが可能になります。
マルチスレッド・アプリケーションのスレッドの取得(1つのみ)
長時間実行中のアプリケーションの断続的なエラーの取得
ロギング機能を使用すると、アプリケーションの追跡やデバッグ、および詳細ログ出力の生成が可能になりますが、パフォーマンス、スケーラビリティおよびセキュリティに関する問題が多少あります。
パフォーマンスとスケーラビリティの問題
ロギングは、パフォーマンスにかなり影響します。ただし、JDBCロギングは一般に本番システムでは有効ではありません。ロギングが無効の場合、パフォーマンスへの影響はありません。
スケーラビリティにも悪影響があります。ロギングには、多くの共有リソースへの保護アクセスが伴うため、結果として、スケーラビリティが大幅に低下します。これはjava.util.logging
フレームワークの問題です。ただし、通常の本番システムではJDBCロギングが有効ではないため、スケーラビリティへの影響はありません。
セキュリティ上の問題
フル・ロギングが有効な場合、すべての機密情報がほぼ確実にログ・ファイルに公開されてしまいます。これはロギング機能の内在的問題です。ただし、特定のJDBC JARファイルにのみ、JDBCロギング機能が含まれます。次のJARファイルにはフル・ロギングが含まれるため、機密を扱う環境での使用はお薦めしません。
ojdbc5_g.jar
ojdbc5dms_g.jar
ojdbc6_g.jar
ojdbc6dms_g.jar
次のJARファイルには、限定されたロギング機能が含まれます。
ojdbc5dms.jar
ojdbc6dms.jar
注意: データベースのユーザー名とパスワードは、これらのJARファイルによって作成されたログ・ファイルには表示されません。ただし、SQL文、定義された値またはバインド値の一部である機密ユーザー・データは、これらのJARファイルのいずれかを使用して作成されたログに表示されます。 |
JDBC診断能力管理機能には、MBean、oracle.jdbc.driver.OracleDiagnosabilityMBean
が導入されています。このMBeanを使用して、JDBCロギングの有効化および無効化が可能です。
関連項目: OracleDiagnosabilityMBean APIの詳細は、次のWebサイトにあるOracle Javadocを参照してください。
|
将来のリリースでは、このMBeanはJDBC内部関数に関する他の統計情報を提供するように拡張されます。
セキュリティ上の問題
この機能により、JDBCロギングを有効にできます。JDBCロギングを有効にするには、特別な権限は必要ありません。ただし、ロギングが有効になると、ログ出力を生成するために標準のJava権限LoggingPermission
が必要になります。この権限がない場合、ログを生成するすべてのJDBC処理でセキュリティ例外がスローされます。これは標準のJavaメカニズムです。