• 締切済み

PHP memory limit 対策アプローチ

昨日構築しているシステムで PHP Fatal error: Allowed memory size of 268435456 bytes exhausted 突然が多発しました。 検索すると「このエラーが出たらPHP.INIのMemory_limit を上げる」と書いてありますが 理由がわからず上げることはNGと上長から言われておりますのですが調査をしたく ただ原因がわからない状態です。アプローチが正しいかアドバイスいただけますと ありがたいです。 ----------------------------------------------------------------- ●発生について 昨夜 21:00位画面上でページが見つかりませんとなる error_logを見たら Fatal error: Allowed memory size of が多発 ↓ Apacheの再起動(stop → start) 解消せず ↓ 検証としてphp.ini を 256mb → 512mbに変更 :解消したが上長承認ないので256mbに戻す ↓ 23:00頃仮想サーバの再起動 →直後すぐにページ確認したが解消せず ↓ 物理サーバの再起動 → 直後すぐにページ確認したが解消せず ↓ 23:45 何もしないでいつの間にか解消 ●ERROR_LOGでみる発生場所 $row = mysql_fetch_array($rs, MYSQL_BOTH) ※MYSQL_BOTH便宜上この設定 ※こちらの対象テーブルが劇的に昨日今日で増えたということはない ●PHPのバージョン 5.1.6 (←古いのでUPGRADEしようとは思っています)   現在のmemory limit = 256mb ●当時の仮想サーバのメモリ状態 topコマンド確認し、2.5G-3Gのメモリフリー ----------------------------------------------------------------- 調査のアプローチ (1)発生プログラムでの処理について A ログイン(特権)→カレンダー表示 : 上記エラー   B ログイン(通常)→カレンダー表示 : 問題なし AとBの違いはAのほうがBよりも3kb程度多めの情報をSessionに入れている Sessionに入れている情報が多い=メモリを使った との検証をしたが256mbとはけた違いに 少ないためプログラムが起因とは考えられない。 (2)該当プログラムだけでMemory 256上限に行くとは思えず  メモリリークが同時に発生していたとしか想定できない(PHP Version 5.1で発生しやすい?)  ただしここはログにも残らず想像 結論 暫定対応は該当PHP上でmemory_limit 指定(PHP.INIが変更できないので) 恒久対応はPHPのVerUP アプローチがやや強引でしょうか?発生原因を特定することは不可能でしょうか? ★疑問点 仮想サーバ・物理サーバを再起動してもダメだった。メモリリークであるならば これで解消するはず 来週月曜日に対応策を上長に提示したいです。 調査方針の指摘事項などなんでもいいので何かアドバイスをいただけませんでしょうか?

  • PHP
  • 回答数2
  • ありがとう数2

みんなの回答

noname#244856
noname#244856
回答No.2

> (PHP Version 5.1で発生しやすい?) メモリーリークの問題以前に、保守ではない新規案件で5.1を使用する時点で問題ありです。バージョンアップ出来るなら早急に行うべき状況です。5.3ならまだしぶしぶ使えなくもないかなというところですが、5.1は本当にありえないです… 【サポート中】 7.0: パフォーマンスが大きく改善された最新版。新機能も盛り沢山。「mysql_*」関数が完全削除された。 5.6: 新しい演算子により可変長引数が使いやすくなった。 5.5: ジェネレータやarray_column関数が目玉機能。「mysql_*」関数が非推奨指定された。 【サポート切れ】 5.4: 6.0になるはずのものが予定変更でこれになった。新機能も盛り沢山。 5.3: 少し前まで最も普及していたであろうバージョンがこれ。名前空間や無名関数が使えるようになり、ようやくモダンな言語に肩を並べられるようになった。データベース抽象化レイヤーとしてのPDOが実用的なレベルになった。 5.2以前: 話にならないほど圧倒的な機能不足。まだこの頃のPDOにはバグがあり、実用的ではない。 7.0の正式版が数日前にリリースされ、apt-getなどでも既にインストール出来るようになっております。「Phalconフレームワークを使っている」「mysql_*関数を書き換えるコストが高すぎる」などの事情が無ければ7.0を導入すべきです。 原因の特定に関してですが、ロジックの問題はありませんか?単純にmemory_limitを上げれば解決するか、というと微妙な気がします… A. 関数が無限再帰している B. create_function関数がキャッシュ無しに相当数コールされている C. 対象テーブルのレコードが多すぎる Aの場合はロジック自体を見直すべきです。Bの場合は function create_lambda($args, $code) { static $cache; if (!isset($cache[$args][$code])) $cache[$args][$code] = create_function($args, $code); return $cache[$args][$code]; } とラップすることで解決されます…が、そもそも5.3から自動的にメモリ解放される無名関数が使えるのでこんなことしなくて良いはずです… Cの場合もSQL文を見直すべき状態です。「全部出してきてforeachで必要なものだけを抜き出す」ようなコードを書いているのであれば大きな誤りで、SQL文一発で必要な分だけ取ってくるように書くべきです。それでもやむを得ないのであれば、非バッファリング版の関数を使うことで、速度は犠牲になりますがメモリ使用量は大きく抑えることが出来ます。 PHP Manual - mysql_unbuffered_query http://www.php.net/mysql_unbuffered_query ただ先ほどから述べているように、「mysql_*」な関数はもう全て新しいコードとして書くべきではないような状態なので、PDOに書きなおすことを検討すべきです。その上で7.0も導入しましょう、パフォーマンスもめちゃくちゃ良くなるので損はないと思います。

webmas_yuto
質問者

お礼

ありがとうございます。年明けにVerUP計画をしていた矢先でした。 実際は全ての処理の前後にMemoryを表示し、明らかに増えている箇所を確認 → ソースコードを確認 ある条件で並び替えた1件のみ取得するためのSQL文が全件取得し変数に突っ込んでいたので SQL文を改善し 1/50程のメモリ使用量になりました。 ありがとうございました。 12/18発生お返事が遅くなってしまって申し訳ありません。

  • hogusyaki
  • ベストアンサー率34% (26/76)
回答No.1

ログ等が残ってないのであれば現時点で原因特定の可能性が難しいような気がしますね。。 ◯Fatal error: Allowed memory size of *** bytes exhausted.の原因を特定する http://akiyama.hatenablog.jp/entry/2015/02/22/153010 こちらのサイトで紹介されているような感じで、register_shutdown_function関数とmemory_get_peak_usage関数の合わせ技でより詳細に調べることもできる気がするので、(もう1度エラーが発生しないとダメですが…)それで原因特定の上、memory_limitをあげるという感じであれば上長も納得されるのでは…と考えました。。 検証環境などでなんとか再現できるとよいんですけどね… メモリ周りが詳しくなくてあれですが、時間的にアクセス過多によってメモリの確保が難しかった…とかありえますでしょうかねぇ…それであれば再起動しても治らなそうな気がしました。的外れであればすみません>_<

webmas_yuto
質問者

お礼

ありがとうございます。おっしゃる通りmemory関数を使って地道に各処理の前後で調べました。 ある条件で並び替えた1件のみ取得するためのSQL文が全件取得し変数に突っ込んでいたので SQL文を改善し 1/50程のメモリ使用量になりました。 ありがとうございました。 12/18発生お返事が遅くなってしまって申し訳ありません。

関連するQ&A

  • phpでメモリーが足りないと表示されます

    現在phpでプログラムを組んでいます 100M程度のcsvファイルを処理したいのですが一旦配列に格納して処理しようとした際 memory exhausが発生してしまいます ini_set('memory_limit', '~M'); memory_limit = -1 などは試してみたのですが毎度128M程度でmemory exhausが発生します 環境は OS:Windows7 XAMPP 1.7.3 PHP: 5.3.1 です またメモリーは6Gほどあります 回答お願いします

    • 締切済み
    • PHP
  • PHPの--enable-memory-limit

    PHPのconfigure時の--enable-memory-limitを調べると 「メモリ制限のサポートを有効にしてコンパイル」 と書かれているのですが、良く分かりません。 具体的に、どのような効果が得られるのかご存知の方が いましたら教えてください。

  • phpでmb関数が使えない

    phpでmb_strlen関数を使おうと思ったら、Call to undefined function mb_strlenとエラーが出て使えません。調べたら他のmb関数も使えないようです。vagrantで作った仮想サーバなのですが、php.iniの設定がおかしいのでしょうか?

    • ベストアンサー
    • PHP
  • phpで巨大なファイルをアップロード

    お世話になります。 PHP・Apacheを使用して大きな容量のファイルをアップロードしようとしています。 php.iniで下記のように値を変更しました。 max_execution_time = 1800 max_input_time = 1800 memory_limit = 2048M post_max_size = 2048M upload_max_filesize = 2048M default_socket_timeout = 1800 この状態でApacheを再起動して1.2GBほどのファイルをアップロードしてみたのですが エラーも起こらず、正常にアップロードされたかと思ったら160バイト程の容量でサーバーにあがっていました。 600MBくらいのファイルでためしたところ正常にアップロードされたのですが 1GB以上のファイルをアップロードするためにはまだなにか設定が足りない、または間違っているのでしょうか? サーバーはCentOS5.5の64bit、メモリは16GBあります。 回答よろしくお願いします。

    • ベストアンサー
    • PHP
  • IIS6.0で、PHP5 Mysql4.1の環境構築がしたい!!

    IIS、php5、mysql4.1のインストールも終わり、 phpもちゃんと動作しているんですが、 なぜか、mysqlとphpの連結がうまくいきません、 同じ風にxpで、IISの代わりに仮想的にApacheで環境を作ったんですが、そっちはうまく動いています、 なぜか、2003serverのIIS6.0で環境を作るといきなりphpが、 mysqlを認識してくれません。(phpinfoで確認済) ODBCですか? 因みに、libmysql.dll php5ts.dll はあるべき場所にあります。 php.iniもmysqlの;も取って、有効にしているんですが・・・ ヒントでも結構です。是非ご教授ください。

  • php.ini以外でメモリ制限ってありますか?

    今、phpexcelを利用して帳票出力を行っているのですが、 こちらで触れないサーバ上で動かなくて困っております。 自前の作業用サーバでは、php.ini上でメモリ制限を解除して動かしているのですが、 問題なく出力されます。 データ環境はmysqlからデータを取得しており、件数が1万件と多く、 出力時の最大メモリ利用量は1Gちょっとです。(罫線描写でかなりメモリを食います) こちらで触れないサーバでphp.iniを1.5Gに解放してもらったのですが、 fatal errorも出ず、ブラウザがそのまま作業中(砂時計マーク)な感じでまったく動かなくなります。 そこでもしかしたら、php.ini以外でメモリを制限しているところがあるのではと考えたのですが、 apaheあたりがあやしいのではと考えました。 他にもメモリ制限するところというのはありますでしょうか。 あちらのサーバ環境は OS:cent os メモリ:4G CPU:core2duo です。 どなたか知識を貸していただけると助かります。よろしくお願い致します。

  • ソケットエラーについて(PHP+MYSQL)

    過去ログもたくさんでていたのですが、解決しないので質問します。 PHPとMYSQLを連動させて使用したいのですが、わからないなりにサーバーの設定しています。 Fedora Core3 PHP Version : 4.3.11 Apache Version : 2.0.53 MYSQL 5.0.24a で設定しています。 PHP単体では動いています。 MYSQLもターミナル上では動いています。 PHPからの動かすと DB Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13) と出たので、 mysqldをもう一度起動してみたり php.iniを /tmp/mysql.sock に変更してApacheを再起動したり my.cnfも同じ値にしているのですが (mysql.socは/tmp/にある) エラーが DB Error: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (13) に切り替わっただけでした。 mysqldが動いていないのかなーとも思うんですが どこから手をつけていいのかわからなくなっています。 ひとつ気になるのが、PHPのテストファイルで取得したinfoの MYSQLの 項目で MYSQL_SOCKET /var/lib/mysql/mysql.sock と出ていました。 これって関係あるんでしょうか。 別の設定があるのでしょうか・・・ それともやっぱりmysqldをあたってみたらいいのか。 みなさんのご意見をお聞かせいただければ幸いです。 あと参考になるような本があれば教えてください。 よろしくお願いします。

  • メモリーが足りないのでしょうか?

    先の質問番号857で質問した者です。857の問題とは別問題で関連がないと思いましたので別にしました。 同じシステム上での問題です。 PHPとMySQLを連携させた入力登録画面を作成しています。サーバーはRedHatです。ブラウザは、InterNet Explorerです。システム上のメモリは512MBです。しかしRedHatシステム管理者がモニターしてくれた話ではメモリは最高に使われた場合でも100MBは余っているようです。スワップも余っているそうです。そこで、PHPに詳しい方に聞くように言われました。 メッセージだけ見るとメモリーが足りないように見えますが、全くわかりません。 当方頼れる方がいません。宜しくご指導お願いします。 問題 Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 184320 bytes) in /home/websites/a.php on line 228 問題についての補足 こちら問題は、特にこのline 228だけで出るのではなく、一度このエラーが出始めると、不特定多数のPHPプログラムのあらゆる部分で同様のエラーが出始めます。 本当にあらゆる部分です。SQL文を発行しているような特別な部分ではなく、項目を移動しているような、単純な部分で出ます。そしていつも同じ場所で出るのではなく、文字通りいたるところでエラーが頻発します。

    • 締切済み
    • PHP
  • PHPでOut of memoryのエラー解消方法

    オープンソースのPHPをレンタルサーバにアップロードし、アクセスすると、 最初は動作していたのですが、突然以下のエラー画面になってしまいました。 Fatal error: Out of memory (allocated 19136512) (tried to allocate 250744 bytes) in それ以降、何度アクセスしてもエラー画面しか出なくなってしまいました。 Windows7で使用しているブラウザはChrome、IE11の最新版ですが、ブラウザを再起動しても解消されず。 レンタルサーバのサポートセンターに問い合わせたのですが、 サポートセンター側ではエラーが出ずに正しく表示されたそうなので現象確認ができませんでした。 試しに私の別のPC(Win7)で試したところ正しく動作しました。 結局、私のメインのPCからは使えない状態です。 エラー内容でググって、 .htaccessに php_value memory_limit 64M を記述してrootに置いてありますがメインPCからだけは動作していないという現状です。 (他のPCでは動作しています。) 原因や対処法など心当たりがあれば教えてください。

    • ベストアンサー
    • PHP
  • php.iniの設定について

    連続の質問で、恐縮ですが、教えてください。 新しいレンタルサーバーで、php4.3.9+mysqlでプログラムしているのですが、 設定が変わったためか、実行時のエラーが表示されません。 php.iniの設定により、表示させることができると思い、関連のサイトを見たのですが、上手くいきませんでした。 すみませんが、実行時のエラーを表示させる設定を教えてください。

    • ベストアンサー
    • PHP

専門家に質問してみよう