我需要管理经典数据库和大量xls文件之间的服务器上同步。
如果它们已同步,我将通过DB执行所有操作,并且没有任何问题。
定期将其中一些文件添加到服务器,我需要同步它们。它们可能很少,但很长,数十万行。
如果我抓到了新的,我开始同步程序。事实证明,同步程序的持续时间不应超过对于1个文件 30secs 之后PHP触发的Maximmum执行时间。但是当我有更多文件时,它可能超过它。
我无法覆盖PHP时间限制。
现在我有一个事务,如果上次文件同步失败,则回滚。 并且必须重新加载页面,直到我看到 sync failed / succeeded 消息。 这有效,但它并不是很好。
选择:
更合适的选择是什么?有没有第三种方式?
答案 0 :(得分: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());
Becaus你说你正在同步一些数据,你可能还需要一个文件(或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