- PR -

ASP.NETアプリケーションにてORACLEのセッション数が増加する

投稿者投稿内容
よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 2005-05-26 14:37
環境:
サーバ OS:Windows2000
DATABASE:Oracle8i
FrameWork1.1.4322.573.


ASP.NET+ADO.NET+ORACLE8iにて開発をしています。

各PAGEのPage_loadでログインを行い。(簡略化)

簡略化
myConnection = New ADODB.Connection
mySqlCommand = New ADODB.Command

myDbTypeName = DbTypeName
myConnString = ConnectionString
myUser = User
myPass = Pass
DbName = DbSource
myConnection.ConnectionString = myConnString

各PAGEのPage_Unloadでログアウトをするようにしています。(簡略化)

myConnection.Close()
myConnection.Dispose()
myConnection = Nothing
mySqlCommand = Nothing
System.GC.Collect()

(最後はガーベージコレクションを発行してます)

@作業をしている人は80人くらいなのですが、通常はオラクルのセッションは
 せいぜい6セッションくらいしか立ち上がりません。(完全の同時接続はない為?)

Aしかしなんらかの処理を実行された後はセッションの再利用が行われずに
 次々にセッションが立ち上がります。

Bその後はASPのワーカプロセス(apsnet_wp.exe)のメモリ使用量がどんどんあがり
 (通常200MGくらいが500MGまでに)

Cセッションは切れずにどんどん立ち上がりますので180セッションくらいに
 立ち上がり、最終的にはOracleに新規者の人がログインできなくなってしまいます。
 またメモリエラーのエラーをサーバがブラウザが返したりします。

Dこうなった場合には運用をとめれない為にワーカプロセスを強制的に終了します。
 するとオラクルのセッションも消えてなくなります。

そこで考えられるのがある画面の処理でオラクルの表などをロックしてしまい。
他の画面からもその処理待ちにてオラクルセッションを掴みっぱなしになり
次々にセッションは新規につくられていくのかなと思いロック状況などを
SQLplusで調べたり、dbostudioにてOracleのセッションがactiveの状態
のままのものを調べてみましたが該当するものもありませんでした。

Oracleのセッションが再利用されない場合としては何が考えられるでしょうか?
またこのような状態に陥らせているタスクを調べる方法はあるでしょうか?
IISのログを採取してみて画面のtoken-timeなどを見てもこれといった画面はな
さそうなのですが・・・・

どなたか心当たりある方がいたらご教授をいただけたらと思います。


けに〜
会議室デビュー日: 2002/09/25
投稿数: 9
投稿日時: 2005-05-26 17:26
こんにちは
外していたら無視してください。

特性の製品名を出していいのかわかりませんので製品名は伏
せますが、とあるサードパーティ製品で同様の問題が発生し
たことがあります。

その製品側のモジュールでOracleに接続して問い合わせする
動作をさせていたのですが、どうやっても問い合わせに使用
したセッションが残ってしまう問題がありました。

その時は、その製品のモジュール側での問い合わせをやめて
.NET側で DataSetオブジェクトを作成してそのモジュールに
渡すやり方に変更して回避することができました。

参考になるとよいですが。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-05-26 18:18
引用:

よねちんさんの書き込み (2005-05-26 14:37) より:
ASP.NET+ADO.NET+ORACLE8iにて開発をしています。


環境は正確に。コードを見る限り、ADO.NETを使っているようには見えないのだけど。本当はADOを使っているのではなくて?
.NETアプリケーション作るなら、ODP.NETを使うのが一番のお勧めなのだけど・・・。それが無理ならData Provider for Oracleとか、Data Provider for ODBCとか、Data Provider for OLEDBとか・・・。

ADOのインスタンスを開放しないシーケンスが存在する可能性が高いと思います。ConnectionやCommand以外のインスタンスはどうしていますか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-05-26 23:19
 この手の話題はワンサとあるんですけど、データベースへの接続は、使用する直前に開いて、使用した直後に閉じましょう。

 Page.Unloadイベントハンドラにログ*1を仕込んで、このイベントが期待しているタイミングで発生しているか、確認してみてください。GC.Collectなんて関係ないです。

*1:開発環境でSystem.Diagnostics.Debug.Writeで書くようにして、ワーカープロセスをデバッガでアタッチ。デバッガの「出力」にいつ現れるか、確認します。


 おそらく、「クライアントに返信がされた時点」でUnloadイベントが発生することを期待しているでしょうが、そんなところでは発生しません。これはメモリからアンロードされるとき、つまり、GCがコレクトするときに発生します(だから、GC.Collectなんてするだけ無駄)。

 接続プールの機能はドライバが持っていますから、DbConnection.Closeを発行しても、接続は閉じません。このため、パフォーマンス的な問題はほとんど無いので、使用の前後でOpen/Closeしましょう。(って、何度書かれていることか)

 で、「改修が大きすぎますぅ」ってことなら、次善策として、Renderメソッドをオーバーライドし、基本クラスのRenderを呼び出した後、接続を切るようにしてみましょう。

_________________
よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 2005-05-27 12:47
みなさん返信ありがとうございます。

けに〜さん

>その時は、その製品のモジュール側での問い合わせをやめて
>.NET側で DataSetオブジェクトを作成してそのモジュールに
>渡すやり方に変更して回避することができました。

サードパーティはDB操作の場面においては使用してません。


甕星さん

>環境は正確に。コードを見る限り、ADO.NETを使っているよう
>には見えないのだけど。本当はADOを使っているのではなくて?

すみません認識不足でした。ADOを使用してです。m(_ _)m

Jittaさん

>この手の話題はワンサとあるんですけど、データベースへの接続は、
>使用する直前に開いて、使用した直後に閉じましょう。

確かにそうですよね。なんでイベントが違う個所にloginとlogoutが
あるのか不思議に思ったのですが、開発したところが当方でないので
そのまま使用している次第です。(>_<)

>Page.Unloadイベントハンドラにログ*1を仕込んで、このイベントが
>期待しているタイミングで発生しているか、確認してみてください。

一応処理的には期待どおりに動いているようです。

login

処理

logout

のように。ただなん時でもサーバボタンの場合にはloginとlogoutが
走るのが気にいらないのですが。(なぜこんな作りなのか・・・)

>GC.Collectなんて関係ないです。

そうなんですよね。ガーベージコレクションはframeWorkが自動で
行うので関係ないとは思ったのですが、ワーカプロセスのメモリ
使用量が常に増えつづけいたのでプログラムで強制的にガーベージ
コレクションをいれてみました。結果は変わらずでした・・・
ここのスレッドを見たところメモリ使用量は適度な大きさにならな
ければそのままと書いてありましたね。必要なときにメモリを開放
するのですよね?

状況をもう少し説明しますと

・・DBO STUDIOにて
Oracleのセッション状況は画面を出力すると1セッション立ち上がり
そのままなにもしないと3分ぐらいで落ちます。

セッションID 状態 Program
1      ACTIVE or INACTIVE aspnet_wp.exe

こんな感じでプログラムを実行すると状態がACTIVEになり処理が終わる
とINNACTIVEになります。

なので同時処理をしたとしてもせいぜい6つくらいしかあがりません。
それでたいていの時間は落ち着いているのですが、不定期に突然セッション
がいくつも立ち上がってくるのです。その後はどのセッションも全然落ちな
いまま新規に作成されてしまい。170セッションくらいがあがると入ること
さえもできなくなります。

そこでサーバのタスクマネージャにてaspnet_wp.exeを強制的に終了します。
そうすると170セッションの接続がすべて落とされて、再び誰かが接続する
とaspnet_wp.exeが2つくらいセッションを作成してきます。それで当面は
正常にセッションは2〜6くらいで運用されていきます。

もしかしたらプログラムのlogoutの処理をとおらない画面が1つでもあった
場合に、このような現象になるのでしょうか?問題が起きる時間帯は不定期
であり、推測としてはなにかの画面がトリガーになりセッションが再利用さ
れなくなるのかなと思うのですが、その画面をどうやったら見つけられるの
かとセッションが次々に立ち上がる原因が全然つかめずに困ってます。

>で、「改修が大きすぎますぅ」ってことなら、次善策として、Ren
>derメソッドをオーバーライドし、基本クラスのRenderを呼び出し
>た後、接続を切るようにしてみましょう。

そうなんです。ものすごい改修作業になっているのでJittaさんのいう
Renderメソッドをオーバライドするやりかたを、もう少し具体的にご教授願えませんか?

とにかく頭が痛い状況となってます。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-05-28 00:57
引用:

よねちんさんの書き込み (2005-05-27 12:47) より:
そうなんです。ものすごい改修作業になっているのでJittaさんのいう
Renderメソッドをオーバライドするやりかたを、もう少し具体的にご教授願えませんか?


言語は何?
質問の内容から、たぶんVB.NETなのかなぁとは分かりますけど。
コード:

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(writer)
myConnection.Close()
myConnection.Dispose()
myConnection = Nothing
mySqlCommand = Nothing
End Sub




_________________
甕星 <mikahosi@abox9.so-net.ne.jp>
http://blogs.msmvp.jp/mikahosi/

[ メッセージ編集済み 編集者: 甕星 編集日時 2005-05-28 01:00 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-05-28 04:42
> 一応処理的には期待どおりに動いているようです。
 ん?ワーカープロセスからDisposeされているのかな?

 だとすると、Renderの件は無効です。甕星さんの、『ADOのインスタンスを開放しないシーケンスが存在する可能性が高いと思います』になります。

> もしかしたらプログラムのlogoutの処理をとおらない画面が1つでもあった
> 場合に、このような現象になるのでしょうか?
 そうなります。すべてのコードを洗い直し、Closeしないパスがないか、検証するしか有りません。
 手っ取り早く確認するには、すべてのClose処理に画面名を出すログを仕込むことですね。

_________________
よねちん
ベテラン
会議室デビュー日: 2002/09/18
投稿数: 55
投稿日時: 2005-05-28 18:31
甕星さん、Jittaさん
返答ありがとうございます。

>言語は何?
>質問の内容から、たぶんVB.NETなのかなぁとは分かりますけど。

VB.NETです。

> Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
> MyBase.Render(writer)
> myConnection.Close()
> myConnection.Dispose()
> myConnection = Nothing
> mySqlCommand = Nothing
> End Sub

ありがとうございます。
参考にさせて頂きます。
ただわかったことなのですが
アプリケーションがありました。

> だとすると、Renderの件は無効です。甕星さんの、『ADOのインスタンスを開放しないシーケンスが存在する可能性が高いと思います』になります。
> もしかしたらプログラムのlogoutの処理をとおらない画面が1つでもあった
> 場合に、このような現象になるのでしょうか?
> そうなります。すべてのコードを洗い直し、Closeしないパスがないか、検証するしか有りません。
> 手っ取り早く確認するには、すべてのClose処理に画面名を出すログを仕込むことですね。

確認してみました。
みるとlogoutしていないものが存在してました。
実行するとフレームが3つある画面でpage_loadでLoginして
page_endにてLogoutされていないものがありました。
そうするとセッションは3つ立ち上がります。複数の人が
同じ画面を立ち上げると次々にセッションはあがることを
確認しました。
なのでそのpage_endのところにlogout処理を入れて様子を見て
みます。それが原因でしたら幸いなのですが。

正常に処理はされていても、検証時には気づかなかったです。
また結果を報告いたします。

スキルアップ/キャリアアップ(JOB@IT)