- - PR -
急にレスポンスが遅くなる
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2004-03-24 07:46
ACCESS->MSDEとアップグレードしたらどうですかね。
そんなユーティリティがACCESSにあったような気もしますし。 そもそもACCESSをODBC-JDBCブリッジで複数ユーザーで使いまわすのは無理があるような気がします。 | ||||
|
投稿日時: 2004-03-25 12:51
皆様、先日はありがとうございました。
ご提案していただいたResultset,Statementのクローズおよびnullをセットする事により、 現象はピタッと出なくなり、連続稼動しています。 まだまだチェックすべき箇所はあると思いますが、とりあえず落ち着いております。 メソッド内で宣言しているResultsetやStatementなどのオブジェクト変数は、 GCによってメソッドを抜けた時に破棄されるものと思っていました(それも極めて早いタイミングで)。 以前に「GCがいつ実行されるかはわからない」と習った事がありましたが、今回の件と関係しているのでしょうか。 明示的にする事により、ここまで違いが出るとは知りませんでした。 いづれにしても、コードが乱暴でありました(反省)。 今までJAVAで数本PGを書きましたが、振り返るのが怖いです。 | ||||
|
投稿日時: 2004-03-25 13:13
まずは問題解決おめでとうございます。
まだ勘違いがあるようですので、是非リソースの解放と GC の違いは勉強しておいてください。Java の仕様も学習された方がよろしいかもしれません。 (1) 参照されなくなったオブジェクトが占めるメモリは GC により解放される。 ただし、実際にいつ解放されるかはプログラム上ではわからない。 (2) Connection, Statement, ResultSet 等のオブジェクトが占めるメモリは GC で 解放されるかもしれない。けれども、DB サーバ側では AP サーバ側で解放されたことを知る close() 以外の方法は、(一般には)ない。 きちんと close() 等の終了処理を行わないと、DB サーバ側でゴミリソースが溜まってしまう。 # 以下余談: # 普通はきちんと close() してやらないとこういう状態になるはずですが、Oracle だけは # そこを何とか頑張ってくれるのか、ResultSet が生きている状態で Statement を # close() してしまったり、全然何も close() しなかったり、オブジェクトのライフサイクル # 管理がズタボロでもまともに動いてしまった経験があります。 # 他の DB に変更したところたちまち露見して大慌てしましたが、結局 Oracle が # プログラマの責任まで面倒見過ぎという結論でした。 Connection や Statement は作って使って解放するまでをきちんと行うのが行儀の良く問題が起こりにくいプログラムです。 programming tips としては、SQLException 等の捕捉に try〜catch 構文を使っていると思いますが、finally 節で close() する習慣を付けると良いかもしれません。 (DB だけではなく、ファイル等のメモリ以外のリソース一般を扱う場合にも使えます) [ メッセージ編集済み 編集者: Gio 編集日時 2004-03-25 13:15 ] | ||||
|
投稿日時: 2004-03-25 13:41
コネクションを閉じるのは当たり前として、StatementとResultSetに関しては、
下記のような仕様となっています。 以下は、サンのJDBC APIドキュメントからの抜粋です。 <抜粋> 4.1.4 Statement を閉じる Statement オブジェクトは、Java ガベージコレクタによって自動的に閉じられます。 ただし、Statement オブジェクトが必要なくなった場合には、明示的に閉じるようにプログラミングしておくことをお勧めします。 Statement オブジェクトを閉じるとただちに、DBMS のリソースが解放され、潜在的なメモリでの問題が起こるのを防止できます。 5.1.20 ResultSet オブジェクトのクローズ 通常、ResultSet を閉じるには、何もする必要がありません。 これは、Statement オブジェクトが閉じられるとき、再実行されるとき、または一連の複数結果から次の結果を検索するために使用されるときに、ResultSet を生成した Statement オブジェクトが、ResultSet を自動的に閉じるからです。 close メソッドは、ResultSet オブジェクトを明示的に閉じるために提供されています。このメソッドは、ResultSet オブジェクトが保持していたリソースをすぐに解放します。 これは、複数の文が使われている状況で、データベースのリソースの競合を防ぐのに十分早い時期で自動クローズが行われない場合に、必要となるかもしれません。 </抜粋> まあ、こんな書き方なので、少なくともResultSetに関しては、 閉じなくても大丈夫そうなのですが、私の経験でも実際に、 これが原因でメモリーリークが発生したことが確かにありました。 (このときはJDBCのバグが原因でした) ですので、ResultSetも明示的に閉じてますね。 それとDBがAccsessですから、JDBCドライバはTYPE1を使用でしょうが、 <抜粋> 9.2 JDBC-ODBC ブリッジ 可能であれば、ブリッジや ODBC ドライバではなくて、Pure Java JDBC ドライバを使用してください。Pure Java JDBC ドライバを使用すると、ODBC が必要とするクライアント側の設定を実行しなくて済みます。また、ブリッジに付属するネイティブコード (たとえば、ブリッジネイティブライブラリ、ODBC ドライバマネージャライブラリ、ODBC ドライバライブラリ、およびデータベースクライアントライブラリ) の中のエラーによって Java VM が汚染される可能性もなくなります。 JDBC-ODBC ブリッジドライバは、プロトタイプの開発段階、および JDBC テクノロジをベースにしたドライバがほかに存在しない場合にだけ使用することをお勧めします。すべて Java で記述された商用の JDBC ドライバが利用できる場合は、ブリッジではなくそのドライバを使用することをお勧めします。 </抜粋> と前出の同ドキュメント内では、上記のように記述されております。 ですから、Accsessを使用していること自体も問題な気もします。 特別な理由が無い限り、DBをMySQLにでも変更した方が良い気がします。 | ||||
|
投稿日時: 2004-03-25 14:04
肝腎なことが抜けていた(_ _)ので補足します。
Oracle が頑張りすぎに見えた現象は次の通りです。 Statement を close() してしまっていても、その Statement が返した ResultSet に next() や get〜() を要求するとエラーや例外が起きずにアクセスできてしまう。 現在 Oracle が手元にないので確認できませんが、単にキャッシュで処理できただけなのか、それとも Oracle JDBC ドライバが close() を遅延してくれていたのかは不明です。私の思い違いかもしれませんし 私自身はリソースオブジェクトのライフサイクルは厳格に管理したい方ですが、JDBC API 仕様ではもう少し緩くても良いというのは知りませんでした。情報の提示に感謝いたします > taku さん (でもシステム負荷を考えると、不要なリソースはなるべく早く解放するというポリシーは捨てられません | ||||
|
投稿日時: 2004-03-25 14:13
unibon です。こんにちわ。
これは内容を読むと、あまり強い理由のようには見えません。こう思うのも、ODBC のデーターソースの設定は「DSN レス」での接続でもできますし、ライブラリのバグは別に ODBC に限ったわけではないからです。 大きな理由は Sun が ODBC を使われては困るからではないでしょうか。 | ||||
