[初回公開] 2010年11月05日
PHP を利用して開発や運用しているとブラウザの画面が真っ白になることがあり、これはプログラムミスやサーバ側に問題がある場合の事象だが、エラーログを見ると「Allowed memory size of *** bytes exhausted」と出ている時の原因と対応方法について紹介する。
このページの目次
1.PHP の「Allowed memory size of *** bytes exhausted」によるエラーの様子
PHP の「Allowed memory size of *** bytes exhausted」によってエラーになる場合は、ウェブサーバのエラーコードが 500 で返ってくる。
デフォルトであればブラウザで PHP を実行して 500 エラーになると画面が真っ白になるが、php.ini でエラーを表示するようにしていれば下図のように表示される。
サーバ OS が Windows でウェブサーバが IIS の場合は OS のデスクトップ上に PHP が強制終了したダイアログが表示されることもある。
ログは次のような記載で残っていることが多い。
PHP Fatal error: Allowed memory size of [メモリ数] bytes exhausted (tried to allocate ** bytes) in [ソースのパス] on line [エラー行数]
2.PHP のエラーログの場所
PHP のエラーログの場所は、サーバ OS やウェブサーバなど利用している環境によって異なる。
エラーログの場所は PHP で指定することも可能で、php.ini で確認することができる。
もしデフォルトのままであれば Windows サーバで PHP を利用している場合は、デフォルトの設定で C:\Windows\Temp\php-errors.log にエラーファイルが保存されている。
また、Redhat でウェブサーバが Apache の場合は /var/log/httpd/error_log に書き出される。
ウェブサーバが Nginx で php-fpm を利用している場合は /var/log/php-fpm/ がログの場所となる。
3.「Allowed memory size of *** bytes exhausted」となる原因
「Allowed memory size of *** bytes exhausted」となる原因は、プログラムした PHP の実行時に大量のデータを扱うなどして、PHP が利用できるサーバ上のメモリが不足している点である。
サーバ OS 上ではシステム以外にミドルウェアや他のサービスなど多くのソフトが動作するためにサーバに割り当たっているメモリが枯渇しないようにサービスごとに制限を設けていることがある。
そのため、PHP が利用できる最大メモリ数も決まっているため、その上限に達する処理量の場合は「Allowed memory size of *** bytes exhausted」となり処理が強制終了する。
4.「Allowed memory size of *** bytes exhausted」の対応方法
「Allowed memory size of *** bytes exhausted」の対応方法としては、PHP が利用できるメモリ量を増やすか、ソースコードとなるプログラム内の処理でメモリを使わないように工夫する点が挙げられる。
4-1.php.ini で memory_limit を変更する
PHP が利用できるメモリ量は設定ファイルの php.ini で指定されている。
設定項目は memory_limit となり、古い PHP では 64MB や 128MB となっているので、この値を 256M や 512M にするとよい。
memory_limit = 256M
4-2..htaccess でメモリサイズを設定する
php.ini はサーバ OS の操作権限がある場合や、高機能なレンタルサーバ(ホスティング)で設定変更が可能だが、サーバ運営業者によっては php.ini の操作を許可していないことがある。
その場合は、ディレクトリ単位で設定できる .htaccess を利用するとよい。
.htaccess には下記の一行を入れることで PHP が利用できるメモリサイズが設定できる。
php_value memory_limit 256M
4-3.メモリを使う処理を避ける
「Allowed memory size of *** bytes exhausted」の原因は前述の通り、PHP 実行時のメモリの不足である。
そのため、メモリを使う処理を避けることでエラーを回避することができる。
PHP は変数に値を入れるたびにメモリを使用する。
そのため、for や forerch のループ処理内で大量に変数を生成させてしまうとメモリ枯渇するので、新しく変数を用意するのは避けたほうがよい。
4-4.unset でメモリを解放する
PHP には変数を破棄する unset 関数が用意されているので、大量のデータを扱うループ処理後などに入れておくことでメモリの枯渇を避けることができる。
また、大量のデータを格納できる配列でも利用できるため、処理後に不要になった配列は unset で破棄しておくと処理速度も速くなる。
4-5.大きいファイルサイズのアップロードはさせない
PHP で実装したウェブアプリケーションでブラウザからファイルをアップロードさせることも少なくないが、PHP はファイルがサーバ上に完全に保存されるまでメモリを利用するため、大きいファイルサイズのアップロードは避けたほうがよい。
アップロード時のファイルサイズの制限は php.ini の upload_max_filesize でも行っており、同じく php.ini にある memory_limit を超えないように値を指定するが、動画ファイルなど 100MB 以上のファイルをアップロードさせる利用シーンの場合は注意が必要である。
4-6.データベース処理の内容を見直す
PHP はさまざまな処理を行うことができ、データベースにある値の操作もその 1 つだが、データベース間の処理で正常に終わらない場合は終了しない処理がメモリに残ったままとなり「Allowed memory size of *** bytes exhausted」となることがある。
例えば pg_get_serial_sequence で指定したシリアルナンバーとインサート時のレコード数が一致しない場合が挙げられる。
ダンプしたデータベースのデータをリストアで createtable とデータの登録を一括で行う際に、serial をカラムに設定したテーブルにpg_get_serial_sequence では 2 としておきながら実際のデータレコードを 3 以上入れてしまった状況とする。
その状況下でアプリケーションからレコードを追加しようとすると serial の計算ができない状態になり、データベース処理がメモリ上にゴミとして残り枯渇に至ってしまう。
そのため、「Allowed memory size of *** bytes exhausted」が出た場合は php.ini の値やソースコードのメモリの使い方以外にも、データベース側にも問題があることがあるため、プログラムがどのような処理をした時に「Allowed memory size of *** bytes exhausted」が出るかもデバッグしながら確認することが大切となる。
関連記事
CSS で div タグ内の上下にできる余分な空白を除去する方法
ウェブサイトやブログを HTML でレイアウトする際に div タグの中に配置した文章や画像の上下に余白が出ることがあり、余白を無くしてデザインや配置の調整を行いたい場合に CSS(スタイルシート)を利用して上下の余白を除去する方…
CSS で float した後ろのパーツも横並びになるのを解決する方法
ウェブサイトのレイアウトやデザインで利用される CSS で div タグ内に記載した内容やリストタグの内容を横並びにするために float を利用することがあるが、float を設定した要素の後ろのパーツも一緒に横並びになってしまう場…
X(旧 Twitter)で同じ Wi-Fi を利用する家族や社員に「おすすめユーザー」に表示されるのを防ぐ方法
X(旧 Twitter)で知り合いとしてフォロー相手の候補が表示される機能があるが、この知り合いが同じ Wi-Fi を利用する家族や社員が表示される現象が発生していると報告があり、原因と「知り合い」に表示されるのを防ぐ方法を紹…