ローカルのシステムでデータベースからCSVファイルを作成して、公開用WEBサーバへFTPアップロード。その後CSVファイルをWEB用データベースに登録する処理を開発しているんのですが、開発用WEBサーバでは正常に完了するのですが、本番用WEBサーバで行うと最初の数万件は登録できているのですが、途中でエラーというか真っ白になって処理がSTOPしてしまいます。
開発、本番用共に同じPHPのファイルを使用しており、データベース構成も同じです。
【相違点】
開発(正常):PHP4.4.2(Apacheモジュールにて動作)
本番(異常):PHP4.4.1(CGI動作)
エラーとなるのも、CSVのファイルの容量によって違います。
ちなみにFTPでのアップロードは開発・運用供正常にできています。
どなたかご教授お願いします。
No.4ベストアンサー
- 回答日時:
がるです。
んと…ちと長くなりますのでご覚悟を(笑
#2さんのおっしゃっている「メモリ」問題の可能性も考えてはいるのですが、今回の件はいわゆる「タイムアウト系かなぁ」お思ってますので、その観点から。
まず「htaccessでは」とのお話しですが…すみませんちょっとこのあたりは。
Timeoutディレクティブなのは把握しているのですが…元々、普段は .htaccess自体を、性能の観点からoffにしているので、あまり詳しくなくて。
もし設定される場合、例えば
Timeout 7200
とかにしておくと、大分よいかと思います。数値の単位は秒です(通常、最近は300が多いのですが…レンタルサーバですと30とかで切ってるかもしれません)。
ただ、.htaccessでTimeoutディレクティブが有効になるかどうかはちとわからないです。
> 10000件ごとに取り込み状況を出力するように変更したのですが、的を外れていますか?
残念ながら。
ちと厳密に書くと。
Apacheのプロセスは、CGI(今回ですとPHPプログラム)を起動します。で、そのプログラムのstdout(標準出力)が完全にcloseし、プログラムが終了した時点で初めて出力を行うのが通常なので。
結局のところ、プログラムが動いている最中は、今まで試した限りでは、「別プロセスにforkした場合」を含め、すべてNGでした。
ですので、ある程度以上の作業であれば、どうしても「裏側で別途処理」という流れになることが多いです。
なので、cronで、という流れになるのですが。
あとは…行数制限をかけてしまうのが、恐らくは現実解なのではないか、と思います。
あまり役に立つ情報でなく大変に恐縮ですが。
お礼が遅くなってしまい申し訳ありませんでした。
アドバイスありがとうございました。
Timeoutディレクティブは.htaccessでは無理でした。
結局、抽出する件数を指定してFTPアップロード→WEBサーバ側で取込後
また抽出といった処理に変更しました。
この方法だと、処理に時間がかかりますが正常に動作しました。
同時にWEBサーバの容量の問題も解決できました。
No.5
- 回答日時:
#2です。
error_logはapacheのerror_logではなくて、phpのerror_logの事だったのですが、設定されていないとの事なので情報は得られないとの事了解致しました。
#1氏がforkで駄目だった経験がお有りとの事で、これから私が説明する手法ーもforkの様なものなのでやはり駄目かもしれませんが一つ。
(尚、今思い付いたので検証はしておりません)
CSVを読み込んでDBに保存するスクリプトを処理単位で3分割します。
a.ブラウザから処理開始のトリガーを引く為だけのスクリプト。
b.単純にCSVを読み込んでDBを更新するだけのスクリプト。
c.bの処理が終了しているかどうかを確認するだけのスクリプト。
まず、ブラウザからaが呼び出されたら、まずは処理開始のフラグを立てます。(ファイルでも良いし、DBに専用のテーブルを用意しても良い)
続けて system() を使ってbを呼び出しますが、その際のパラメータストリングの末尾に "&" を付けます。
具体的には system("/usr/bin/php -q bのスクリプトパス &"); とします。
これでbは常駐扱いとされて直ぐに処理が戻ってくる筈なので、取り合えずブラウザには「更新処理中です」等と出力して終了します。
bは処理が終わったらaが立てた処理中フラグを降ろします。
cは呼び出される都度にaが立てた処理中フラグを確認し、立っていれば「処理中です」と出力して終了。降りていれば「完了しました」を出力して終了します。
このcをaの処理が終わった時に出力されるHTMLのヘッダにmetaタグのrefresh定義を利用して10秒程度の間隔で何度も呼び出す様にします。
c自信も結果を出力する際に、まだフラグが立っていたら同じくmetaタグを仕込みます。(つまり自分を再度呼び出す様に仕掛けます)
頭の中ではイケそうな気もしますが、いかんせん検証していませんので駄目元という事で簡便してください。
アドバイスどうもありがとうございました。
結果的に無事動作するようになりました。
NINJA104さんの処理については今後の参考にさせていただきます。
No.3
- 回答日時:
がるです。
なるほど状況は概ね。
PHPでどれだけの設定をしようとも、最終的には「Apacheの設定次第で切られてしまう」というのが、この場合直接的な回答になろうかと思います。
もうちょっと詳細に書くと。
「CSVを処理している最中にApacheの設定している接続時間を超えた場合にその時点で"処理が片付かない"エラーでApache自身が異常終了として処理してしまう」ため。またファイルサイズによって違うのは「ファイルサイズによってCSV処理時間が異なるため」になります。
Apacheの、通常httpd.confと呼ばれる設定ファイルの中に、接続時間への設定などがあるので。
で、解決策ですが。
httpd.confの設定を長くするのが一つ。下策ですがとりあえず楽ですが、やはりどこかで同じ事象に悩まされます。
CSVファイルが「一定サイズ以上にならない」のであればある程度逃げれるのですが。
上策は「つくりを変える」事。具体的には
・CSVのupload
・CSVの処理
を別々に行います。CSVの処理は、cronあたりでバッチにするほうがよろしいかと。
この方法の場合、どんだけのファイルサイズがあろうとも、基本的には問題なく動きます。
ただ、画面遷移など色々変更がはいるでしょうから、多分大変です。
何かの参考にでもなれば幸いです。
がるさんアドバイスありがとうございます。
Apacheの設定ですが、htaccessではできない項目なんでしょうか?
あと処理の流れはローカルのシステム内でCSV生成後FTPアップロード。
そのあとheader関数でWEBサーバ内のCSV取り込み処理のファイルへアクセス。
そのまま取り込みを行っています。
がるさんが言われている「つくりを変える」と言う内容はこういうことではダメということでしょうか?
cronのバッチ処理は公開用のサーバが対応していません。
いろいろと調べまして、10000件ごとに取り込み状況を出力するように変更したのですが、的を外れていますか?
確かIEの接続時間の関係でこういう処理をすればタイムアウトにならないという情報が検索して見つかったので試してみました。
開発用では200万件のデータの取り込みは正常にできました。
ちなみに開発用のWEBサーバもレンタルサーバです。
もし、ご回答いただければ嬉しいです。
No.2
- 回答日時:
error_logには何が出力されていますか?
私の経験ではメモリが足りなくなった場合に、ブラウザに同じ挙動(真っ白)が返った時がありました。
その場合、php.iniの利用するメモリ上限値設定を見直して余裕を持たせるか、またはメモリを無駄に消費しない様にコードを自力で最適化(必要ではなくなった変数をせっせとunset()する等)して対策を取るかのどちらかですね。
この回答への補足
apacheのerror_logには
「Premature end of script headers:ファイル名・・・」
とありました。
調べてみたのですが、どこかにエラーがありますとしかわかりませんでした。
ちなみに本番用はレンタルサーバになります。
memory_limitは本番、開発共に同じ値(項目なし)です。
CGI版とApacheモジュール版ってちがうのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- サーバー 別サーバに構築したApache+Tomcatの連携について 2 2023/03/06 23:23
- ソフトウェア データベースのウェブでの自作 2 2023/08/01 10:06
- Excel(エクセル) 【マクロ】webアドレスにて指定されたCSVファイル【excelソフト表示】を印刷する件 1 2023/02/15 01:52
- サーバー Laravelをレンタルサーバーにインストールするにはどうすればいいですか? 2 2022/06/29 10:17
- Outlook(アウトルック) 【 Windows 10 】アドレス帳に正しくインポートを完了させたい。 3 2023/04/23 13:41
- その他(プログラミング・Web制作) データ解析ソフトRでのファイル入力read.csvがエラーになります 7 2022/03/27 22:11
- Visual Basic(VBA) VBA アドインについて お詳しい方 ご教授をお願いします。 相談事項 現在以下の対応を実施した所、 1 2022/11/02 16:53
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/21 09:42
- Excel(エクセル) CSVファイルでVBAを動かす方法 3 2023/04/04 10:22
- その他(データベース) 業務用のデータベースサーバーの選び方について 4 2022/11/22 10:22
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
PHPのif文でその処理を途中で抜...
-
PHPが処理を途中でやめる。原因...
-
リンクのラベルを取得したい
-
入れ子になっているHTMLタグも...
-
インスタンス化に伴うメモリ消...
-
関数の前にアットマークが付く場合
-
System関数で変数を受け渡す方法
-
透過PNGが透過されない!!
-
CFileDialogの最初のディレクト...
-
【file_exists】ファイルが存在...
-
フォントの色を変えるには?
-
VB6にてメールを送信する方法
-
C# Excelファイルへの画像挿入。
-
フォームで戻った際に入力済み...
-
.htaccessにphp_valueが使用できな
-
別ファイルの変数を呼び出した...
-
3つ以上の論理積は利用可能なの...
-
onedrive にexcelファイルをア...
-
$_SESSION 有効期限をブラウザ...
-
リクエストメソッド
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
PHPのif文でその処理を途中で抜...
-
インスタンス化に伴うメモリ消...
-
PHPが処理を途中でやめる。原因...
-
PHPExcel処理速度が遅い
-
phpの処理中に画面表示ををする...
-
関数の前にアットマークが付く場合
-
Cronで同じ処理を複数同時に実...
-
PHPで偶数と奇数を判断するには
-
3の倍数の和
-
includeしたファイルに変数を持...
-
タイムアウト処理?となる
-
プログラム内で処理中断後も継...
-
入れ子になっているHTMLタグも...
-
条件分岐 if(elseif) switchの...
-
Smartyにて、文字検索
-
アクセスクライアントごとにタ...
-
VBAからPHPを実行(キック)したい
-
【PHP】URLがドメイン名...
-
DBへの書き込みとメール送信を...
-
GETリクエストでURLを渡す時
おすすめ情報