我需要每天更新MySql中的10000个项目。我上传了一个CSV文件,并尝试更新我的数据库数据。我用两个场地分叉。我的问题是,这是可行的,但过了一段时间,我会得到504网关超时,我的上传无法完成这个过程。
这是我的代码
if(is_uploaded_file($_FILES["filename"]["tmp_name"])){
//
move_uploaded_file($_FILES["filename"]["tmp_name"], "".$_SERVER["DOCUMENT_ROOT"]."/upload/".$_FILES["filename"]["name"]);
$file_path="".$_SERVER["DOCUMENT_ROOT"]."/upload/".$_FILES["filename"]["name"]."";
$file=file_get_contents("".$file_path."");
$file=iconv("windows-1251", "utf-8",$file);
file_put_contents("".$file_path."",$file);
if(!setlocale(LC_ALL, 'ru_RU.utf8')) setlocale(LC_ALL, 'en_US.utf8'); if(setlocale(LC_ALL, 0) == 'C') die(' (ru_RU.utf8, en_US.utf8)');
if (($handle_f = fopen($file_path, "r")) !== FALSE) {
// csv
while (($data_f = fgetcsv($handle_f,99999,";"))!== FALSE) {
// ean13
$sql="SELECT id_product FROM ps_product WHERE reference = '".$data_f[0]."'";
$id_product = Db::getInstance()->getValue($sql,0);
// ,
if ($id_product) {
$sql=mysql_query("UPDATE `ps_product` SET `quantity` ='".$data_f[1]."' WHERE `reference`='".$data_f[0]."'");
echo "<p style='color:green'>Items<b>".$data_f[0]."</b> updated</p>";
} else{
echo "<p style='color:red '>Items<b>".$data_f[0]."</b> not found</p>";
}
}
echo "<b>Update is complited</b>";
}else{
echo "Can`t open imported file";
}
}else{
echo '
<h2>Quantity update:</h2>
<form action="'.$_SERVER["PHP_SELF"].'" method="post" enctype="multipart/form-data">
<input type="file" name="filename"><br>
<input type="submit" value="Load"><br>
</form>
';
}
现在,我在excel中拆分了许多文件,每次失败约1000个,并更新了数据库。这需要一些时间。你能给我一个主意吗,或者我的代码中有一些错误?我认为使用ajax进行更新是没有帮助的。
504 Bad Gateway Timeout
是指网关/代理服务器没有从处理服务器获取timely response
。在这种情况下,即使处理服务器完成了所有更新,因为它没有向代理发送任何消息来让它知道处理仍在进行,代理也会关闭连接。
在这种情况下,使用ajax进行更新不是一个好主意。然而,有一种叫做heartbeat pattern
的ajax design pattern
可以帮助您。基本思想是:
- 您对处理页面进行正常调用以启动CSV更新
- 此外,您在页面中设置了一个javascript计时器,该计时器每X分钟对服务器页面进行一次ajax调用
- 服务器以一条简单的消息进行响应。甚至可以是单个字符
- 您的客户端ajax可以忽略此消息,或者打印它或其他什么
- X分钟后,同样的过程发生
- 与此同时,您在第一步中启动的CSV处理仍在继续
该continuous message request and response
被称为heartbeat
。它有助于在进行服务器处理时保留connection alive
。一旦服务器处理结束并得到确认,就可以根据需要终止计时器并关闭连接。
当然,在处理服务器端,您可以执行其他操作,如increase timeout lenght
、add database indexes
等,以确保不会发生php process timeout
。
但是请注意,进程超时与网关超时不同。
引用上有索引吗?如果你不这样做,每次更新都需要很长时间。
此外,您有一些主要的SQL注入问题,并且mysql已贬值,请切换到mysqli。
我需要将大型CSV加载到MySQL中,并发现最好的解决方案是创建一个可以保存原始CSV数据的表。我制作了与CSV具有相同字段的表,然后使用LOAD DATA
进行批量导入,这很快,然后我可以使用SQL对数据执行必要的查询。
LOAD DATA LOCAL INFILE '{$filename}'
INTO TABLE {$table_name}
FIELDS TERMINATED BY '|'
LINES TERMINATED BY ''n'
一旦您在表中有CSV数据,您就可以简单地在块(LIMIT和OFFSET)Psudeo代码中运行查询,例如
DEFINE("BLOCK_SIZE",100);
// Get the total rows in CSV table so when can divide into blocks
SELECT SQL_CALC_FOUND_ROWS *
FROM my_csv_table
LIMIT 1;
$total_rows = SELECT FOUND_ROWS();
for($counter = 0; $counter < $total_rows; $counter += BLOCK_SIZE)
{
SELECT *
FROM my_csv_table
LIMIT BLOCK_SIZE
OFFSET $loop_counter;
foreach $row
{
// UPDATE YOUR REAL TABLE IF MATCHED
}
}