Oracle Database 11gでは、JDBCドライバが拡張されています。新しい診断機能が追加され、既存の診断機能も強化されています。これらの機能により、ユーザーはOracle JDBCドライバを使用するアプリケーションでの問題や、ドライバ自身の問題を診断できます。また、Oracle JDBCドライバを使用してOracle DatabaseのインスタンスにアクセスするJavaアプリケーションを開発および保守するために必要な労力も軽減されます。
Oracle JDBCドライバには、ユーザーがJDBCアプリケーションの問題を識別および修正することを可能にする次の診断機能が用意されています。
注意: JDBCドライバの診断機能は、標準のjava.util.logging フレームワークおよびjavax.management MBeanフレームワークに基づいています。これらの標準フレームワークについての情報はこの文書では扱いません。標準フレームワークの詳細は、Sun社のWebサイトを参照することをお薦めします。また、使用可能な各種の設定オプションの詳細は、java.util.logging のJavadocを参照してください。 |
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
は、コンテキストClassLoader
でtoString
をコールした結果をフィルタしたものです。
次のとおりにコードを作成します。
// compute the ObjectName String loader = Thread.currentThread().getContextClassLoader().toString().replaceAll("[,=:\"]+", ""); 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ドライバはいくつかのサブ・ログ出力を使用しています。ログ・メッセージをサブ・ログ出力の1つに制限すると、出力が大幅に減ります。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
も使用できます。XMLFormatter
はOracleサポートに送信するログとして最適です。サポートでログ出力をより簡単に自動処理できるためです。
ロギング機能を使用すると、アプリケーションの追跡やデバッグ、および詳細ログ出力の生成が可能になりますが、パフォーマンス、スケーラビリティおよびセキュリティに関する問題が多少あります。
パフォーマンスとスケーラビリティの問題
ロギングは、パフォーマンスにかなり影響します。ただし、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の詳細は、JDBCのJavaDocを参照してください。 |
将来のリリースでは、このMBeanはJDBC内部関数に関する他の統計情報を提供するように拡張されます。
セキュリティ上の問題
この機能では、JDBCロギングを有効化できます。JDBCロギングの有効化には、特別な権限は必要ありません。ただし、ロギングが有効化されてから、ログ出力を生成するには標準のJava権限LoggingPermission
が必要になります。この権限がない場合、ログを生成するすべてのJDBC処理でセキュリティ例外が発生します。これは標準のJavaメカニズムです。