更新大型数据库时,PHP MySQL超时

时间:2016-10-02 20:37:20

标签: php mysql json rest

我有一个MySQL数据库,在外部提供商上有大约600万个歌曲ID,并且可以通过chrooted访问命令行。

我在大约450记录时得到Bad Gateway错误,即使它一直在更新到记录950.它远离完整的数据库,我真的不知道如何处理它。我也试图限制查询,但正如所说它会停止,手动拆分是不可能的(6000手写!!!)

流程概述如下,伪代码后面有更深入的理解:

  1. 从表中检索歌曲ID
  2. 查询外部API(带有json结果的REST)的详细信息
  3. 将完整的歌曲详细信息插入另一个表格
  4. 提前感谢您的帮助。

    伪代码

    ini_set('max_execution_time',0);//INFINITE
    ini_set("memory_limit", "300M");//MAX SUPPORTED BY HOSTING
    
    $query1 = "SELECT id FROM songs";
    $sql = mysqli_query($link, $query1) or die("error");
    
    while ( $row = mysqli_fetch_assoc($sql) ) {
        $url = 'https://api.com/tracks?pass='.$pass.'&id='.$row["id"];
        $content = file_get_contents($url);
        $json = json_decode($content, true);//RETURNS "results" ARRAY
    
        $query2 = "INSERT INTO songs_ok VALUES ";
    
        foreach($json["results"] as $result){
            $query2.= "( ";
            $query2.= $row["timestamp"].",";
            $query2.= $row["artist"].",";
            $query2.= " ),";
    
            $query2 = rtrim($query2,", ").";";
    
            $sql2 = mysqli_query($link, $query2) or die("error");
    
        }
    
    }
    

    P.S。我还尝试将INSERT查询置于底部,但显然结果几乎相同。 THX

2 个答案:

答案 0 :(得分:1)

这是一个硬编码限制。 直到今天一直工作的解决方法

mysqli_query($link, "set @@session.interactive_timeout = 28800");
mysqli_query($link, "set @@session.wait_timeout = 28800");

答案 1 :(得分:0)

首先:正如@cale_b建议的那样,您应该批量插入,这意味着在单个查询中插入更多记录,例如INSERT INTO table (col1, cols2) VALUES (record1, record1), (record2, record2), (record3, record3), etc...

第二:您应该批量从表中检索数据。意思是,一次检索100行(在sql的SELECT和OFFSET中使用LIMIT完成)。

第一件事将使您的数据库服务器不会过载,第二件事将使您的内存不会超载。

另外,请考虑一些Web服务,例如Cloudflare,将最大执行时间设置为您无法更改的特定时间。然后,您应该将脚本作为控制台应用程序运行,因为在控制台中运行脚本没有最长的执行时间。

您可以使用简单的命令从Web应用程序调用控制台脚本:

$command = 'php /path/to/your_script.php > /dev/null 2>/dev/null &';

shell_exec($command);

添加的> /dev/null 2>/dev/null &将在一个独立的过程中启动控制台应用程序,因此它无法连接到您的网络应用程序,并且在网络应用程序进程停止时不会中断。