2

従来のデータベースと大量の xls ファイル間のサーバー上の同期を管理する必要があります。

それらが同期されている場合、DBを介してすべての操作を実行し、問題はありません。

これらのファイルのいくつかは定期的にサーバーに追加され、同期する必要があります。数は少ないかもしれませんが、非常に長く、数十万行のオーダーです。

新しいものを見つけたら、同期手順を開始します。同期手順は、1 つのファイルに対して30 秒後に PHP がトリガーする最大実行時間を超えないように、十分に短いことが証明されています。しかし、ファイルが増えると、それを超える可能性があります。

PHP の時間制限をオーバーライドできません。

現在、最後のファイル同期が失敗した場合にバックロールするトランザクションがあります。同期の失敗/成功のメッセージが表示されるまで、ページをリロードする必要があります。これは機能しますが、あまり良くありません。

選択肢:

  1. register_shutdown_function を使用して、ページの残りを印刷し(可能ですか?)、リロードするように指示します
  2. 制限時間の近くでカスタム スクリプトと同じことを行う
  3. バックグラウンドで同期を完了する方法はありますか? おそらくajaxを介してページに気付くでしょうか?

より適切な選択は何でしょうか? 3番目の方法はありますか?

4

1 に答える 1

2

時間制限を回避するための優れたトリックがありますが、適切に行わないとサーバーの遅延が発生する可能性があります。このスクリプトに基づいて、純粋な PHP CRON の代替案を作成しました。
何をするかというと、HTTP クライアントを切断しますが、スクリプトは実行し続けます。これが最も重要です。そうすれば、スクリプトは istelf でスタックすることなく、自分自身を呼び出すことができます。
これを行うには、http ヘッダー Content-Length を送信することが重要です。

<?php
ignore_user_abort (true);    //Tells PHP to ignore connection state
ob_start();
echo "Loop started\n";
$size = ob_get_length();
header("Content-Length: $size"); //Send exact output size to make sure client disconnects
header("Connection: close");     //Tells client to disconnect
ob_end_flush();
ob_flush();
flush();     //Clean all buffers
if(session_id()!="")
  session_write_close(); //Close the session so that the user can use other scripts on the site
/*Here, the script runs even if client is connected*/
?>

さて、非常に危険な再帰部分があります。複数のスレッドを回避するために、スクリプトが既に実行されていることをスクリプトに伝えるファイルを作成する必要があります。このような:

if(file_exists("secure_key"))
  exit;
else
  file_put_contents("secure_key",time());

一部のデータを同期していると述べたため、同期プロセスに関する情報を保存するために、もう 1 つのファイル (または MySql テーブル) が必要になる場合があります。これにより、おそらくAJAXを使用して、リクエストの進行状況をユーザーに通知できるようになります。これにより、アプリケーション全体が非常にプロフェッショナルに見えます :)
ご存知かもしれませんが、同期しているのが FOR または WHILE ループの場合、開始時刻を一定に保存することも優れているため、問題なく終了して保存できます。

define("STARTTIME",time());  //Right now
define("MAXTIME",ini_get('max_execution_time')); //Max execution time
define("SAFE_EXIT_TIME", 4);  //4 seconds to save & quit

/*preparation*/
while(time()-(STARTTIME-SAFE_EXIT_TIME)<MAXTIME) {
    /*Synchronize*/
}
unlink("secure_key");         //delete the antistuck file
get_headers(/*scriopt url*/); //call itself
exit;                         //quit
于 2013-02-03T18:47:40.543 に答える