- ベストアンサー
メモリリーク対策
トップページを開くたびに、SQLサーバへデータベースを参照し、内容を表示させる、というASPページを作成しましたが、メモリリークが度々起こります。プログラムを調査しましたが、解放していないロジックは見当たりませんでした。とりあえずの対応として、サーバ再起動を1/週で実施するようバッチを作成しました。 しかし、トップページには、 <META http-equiv="refresh" content="1800"> が記述してあり、 もしかしてこのrefreshが問題なのかと思って調べているのですがイマイチはっきりした回答がありません。 恐れいりますが、 refresh指定すると、メモリリークは必ず発生してしまうものなのでしょうか? どなたか教えていただけましたら幸いです。 その際、回避方法なども教えていただけましたら助かります。 以上、宜しくお願い致します。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ひとまず、「DBを使ったWebアプリケーション開発の全面経験者」 という広範囲での経験者です。 質問者さんのシステムで当てはまるかどうかは判りませんが、 質問文の範囲から聞き取れる「システムの悲鳴」から 原因を診察してみます。 [症状] refreshにより繰り返されるストレスの蓄積による慢性疲労。 現在は週1回のサーバ再起動によるストレス発散にて 擬似新入社員状態(?)となり勤務継続しているが、 一週間の連続勤務によって(再起動までの)約336回の ストレスに耐えるのがやっとのようである。 サーバの稼動状態にもよりますが、 週一回の再起動を基準に考えると、 現状のままでは、サーバの起動開始からプログラムがこけるまで 稼動状況が変わらなければ450回付近といった、 ほぼ似通った回数で毎回発生するものと思われます。 [原因と対策] まずは当該ASPスクリプトが常駐する、 もしくはそれに伴う「スクリプトの環境」が 常駐するような設定になっている事が前提となりますが、 メモリリークの原因は「DBコネクションの開放漏れ」 が考えられます。 想定される場所と内容 ・ASPの最初にDBと接続を行っている処理 (最後に対応するディスコネクトの処理が無い) この場合、refreshがかかるたびにコネクトするだけして ディスコネしていないので、結果コネクトするクチが 足りなくなってこける。 ・select句発行に伴うコネクト処理と開放。 (一度にオープンしたままにしようとするクエリが 多過ぎると発生。) この場合はこけるまでのrefresh回数が不定である場合に可能性大です。 抽出したデータを持つだけ持って突合処理をするだけやって、 最後のメモリ開放などの掃除の処理の際に いくつのクエリを保持していたのか管理している変数の値が 処理中におかしくなったなどの理由で 正しく掃除されていないために、掃除し忘れのクエリが残ったままとなります。 それが蓄積された結果、上記のDBコネクトと同様 クエリを発行するためのクチが足りなくなってこけることになります。 質問文で述べられている ・ロジック自体におかしな部分は見当たらない。 ・しかし、しっかりコケルという症状は出る。 ・サーバの再起動で一応対処可能。 という3点から ・システム環境(DB、ASP、ブラウザ(?))の 約束事の設定に忘れていることがある。 点で推測してみました。 時間と手間に余裕があるのならば、 発生条件(回数や件数や同時アクセス数や経過時間)を出来る限り特定して その条件がそろったときに、ロジックのどのような処理の部分が 悲鳴を上げているのか、「ロジックを一旦全部コメントにして」 順番にロジックを甦らせて条件と要因を特定するのが Web系統の開発の1つの手法だったりもします。 それでも「とことん突き詰めていった結果」、 実は「ソフトのバグだった」というオチもあります。 大規模なシステムであるほど「この点でおかしくなる」というのと 「そこで何が発生しうるか」をどれだけ思いつくのかが 意外と大切な開発現場だったりします。
その他の回答 (2)
- takkunnet
- ベストアンサー率74% (32/43)
データベース内容の定期更新のページとのことですが、 1回あたりの表示にかかる時間はどのくらいなのでしょうか? また、たびたび起こるとのことですが、1回表示時、2回表示時のそれぞれのメモリ使用量は明らかに「2倍」近くになっているのでしょうか? 1回目でこけることは無いのでしょうか? SQLサーバではないので関係ないのかも知れませんが、以前、他社のDBを利用しているときにレコードセットの開放をしているにもかかわらずメモリが開放されていないっていう症状に悩まされました。 そのときはgootさんと同様メモリリークが多発したのを記憶しております。 そのときの解決方法としてはDBからのデータ取得を分断させて回避しました。 要は1つのレコードセットで取得するデータ量を減らしたのです。 ただ、gootさんの場合は30分という結構長めの再読み込みですからこれには該当しないかも知れませんね。。。
お礼
回答ありがとうございます。 1回あたりには1秒以下で表示されます。 >そのときの解決方法としてはDBからのデータ取得を分断させて回避しました。 もともと、1回の取得でgetするデータは少ないのでやはり、refreshの問題ではないような気がします。 貴重なご意見ありがとうございました。
- phoenix343
- ベストアンサー率15% (296/1946)
なぜ、メモリリークと分かったのですか? その方法を教えてください。 少なくとも、refresh指定でメモリリークする、なんて話は聞いたことが無いです。
補足
回答ありがとうございます。 >なぜメモリリークとわかったのか IISログ(system32->logfiles)にメッセージが出ていました。(メモリ不足)メッセージが続き、最後サーバダウンしてしまいました。 また、 == 定期的にリフレッシュするときに、(同時に多数)CGIプログラムが読み込まれて、そのプログラムがメモリを正常に解放できないケースが発生するのではないかと。 == というほかの方からの意見をもらいまして、因果関係を調べていたのですが、はっきりわからず質問させて頂いた次第です。 宜しくお願い致します。
お礼
大変貴重なご意見ありがとうございます。 今は、おっしゃられた通り 時間と手間に余裕があるのならば、 発生条件(回数や件数や同時アクセス数や経過時間)を出来る限り特定して その条件がそろったときに、ロジックのどのような処理の部分が 悲鳴を上げているのか、「ロジックを一旦全部コメントにして」 順番にロジックを甦らせて条件と要因を特定するのが ということをしております。 サーバの監視ということで現在運用部署がログ収集やサーバ設定状況、メモリ状況などを監視しているところです。 その結果は、まだ聞かされていない(調査中段階なので)のですが、実は、ずっとエラーが起こっていない状態です。(すいません、結果を聞いてからご報告しようと思っていたのですが、遅すぎて待てないので御礼文を書かせて頂ます。) ひとまず、ロジック的にも問題なく、refresh指定にいたっては、今回の場合全く関係がないと思われますので、今しばらく状況監視を続けようと思います。 そのほか、いろんなパターンでの考えられる原因を探って頂きありがとうございました。今後、他のアプリ開発の時にも役立ちそうです。 ありがとうございました!