2016-10-02 3 views
0

커맨드 라인에 대한 chrooted 액세스 권한을 가진 외부 공급자에 약 6 백만 곡의 ID가있는 MySQL 데이터베이스가 있습니다.큰 데이터베이스를 업데이트 할 때 PHP MySQL이 시간 초과 됨

거의 레코드 450에서 레코드가 950까지 업데이트되는 경우에도 잘못된 게이트웨이 오류가 발생합니다. 전체 데이터베이스와는 거리가 멀고 처리 방법을 모르겠습니다.

  1. : (6000 필기!)

    이 흐름의 개요, 깊은 이해 한 후 의사를 다음과 같다 나는 또한 쿼리를 제한하려고했으나으로 멈출 것이라고 말했다과 수동 분할은 불가능하다

미리 감사드립니다 다른 테이블에 전체 노래 정보를 삽입 자세한 내용은 테이블에서 (JSON 결과에 REST) ​​외부 API

  • 쿼리를 노래 ID를 검색 도와주기 위해.

    의사

    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"); 
    
        } 
    
    } 
    

    추신 또한 INSERT 쿼리를 맨 아래에 넣으려고했지만 명백하게 결과는 거의 같습니다. 들으

    먼저
  • +0

    삽입을 배치하지 않는 이유는 무엇입니까? 'INSERT INTO 테이블 (col1, cols2) VALUES (record1, record1), (record2, record2), (record3, record3) 등등 ...'- 당신은 한 번에 AFAIK 수백 개의 레코드를 삽입 할 수 있습니다. 각각에 대한 쿼리. 또한 인서트는 인덱스가있는 경우 "비싸다"(6 개월 레코드 - AFAIK - 각 인서트로 인덱스를 다시 계산해야 함) 것으로 나타납니다. 이와 같이 빠르게 실행되는 루프와 많은 레코드가 있으면 적어도 삽입을 일괄 처리하면 도움이 될 것입니다. –

    +0

    ** 경고 ** : mysqli를 사용할 때 [매개 변수화 된 쿼리] (http://php.net/manual/en/mysqli.quickstart.prepared-statements.)를 사용해야합니다.php) 및 ['bind_param'] (http://php.net/manual/en/mysqli-stmt.bind-param.php)을 사용하여 쿼리에 사용자 데이터를 추가하십시오. ** 심각한 [SQL injection bug] (http://bobby-tables.com/)를 만들었 기 때문에 문자열 보간이나 연결을 사용하여 **이를 수행하지 마십시오. **'$ _POST' 또는'$ _GET' 데이터를 쿼리에 직접 입력하지 마십시오. 실수로 누군가를 악용하려고 시도하면 매우 위험 할 수 있습니다. – tadman

    +0

    @cate_b 불행하게도 나는 불분명했다. post scriptum에서 읽을 수 있듯이, 나는 벌써 배치 삽입에 실패했다. – fab

    답변

    1

    하드 코딩 된 한도입니다. 오늘까지 완벽하게 작동하는 해결 방법

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

    최대 실행 시간을 무한대로 설정하고 가능한 경우 PHP 콘솔 응용 프로그램 설정을 확인할 수 있습니다. 또한 올바른 답을 표시하십시오. :) – Imaginaroom

    +0

    bash 인라인 for 루프 6500 번? 결과가 0 인 경우에는 db에 대한 업데이트를 건너 뜁니다. – fab

    +0

    단일 라인 루프가 아무런 차이를 만들지 않을 것이라고 생각합니다. – Imaginaroom

    0

    : @cale_b 제안으로, 당신은 두 번째 INSERT INTO table (col1, cols2) VALUES (record1, record1), (record2, record2), (record3, record3), etc...

    같은 단일 쿼리에서 더 많은 기록을 삽입하는 것을 의미 일괄 삽입한다 : 당신이 일괄 테이블에서 데이터를 검색합니다. 의미, 예를 들어 한 번에 100 행을 검색 할 수 있습니다 (SQL의 SELECT와 OFFSET의 LIMIT를 사용하면됩니다).

    우선 데이터베이스 서버가 과부하되지 않도록하십시오. 두 번째로 메모리가 과부하되는 것을 막을 수 있습니다.

    또한 Cloudflare와 같은 일부 웹 서비스에는 최대 실행 시간이 변경할 수없는 특정 시간으로 설정되어 있다는 점을 고려해야합니다. 콘솔에서 스크립트를 실행하는 데 최대 실행 시간이 없으므로 스크립트를 콘솔 응용 프로그램으로 실행해야합니다.

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

    (가) > /dev/null 2>/dev/null &는 독립적 인 과정에서 콘솔 응용 프로그램을 시작합니다 추가, 그래서이 웹 응용 프로그램에 연결되지 않고 :

    당신은 간단한 명령으로 웹 응용 프로그램에서 콘솔 스크립트를 호출 할 수 있습니다 웹 응용 프로그램 프로세스가 중지되면 중단되지 않습니다.

    +0

    안녕하세요, 아마도 내가 명확하지 않았습니다. post scriptum에서 읽을 수 있듯이, 나는 벌써 배치 삽입에 실패했다. 또한 LIMIT 1000을 사용해 보았지만 실제로 "약"레코드 950에서 타임 아웃했습니다 : 6500 번을 멈추고, 오프셋을 다시 계산하고, 6500 번 하드 코드하는 것은 불가능합니다. – fab

    +0

    내가 언급 한 것을 잊어 버린 또 하나의 사실이 있습니다. 일부 웹 서버는 특정 시간으로 설정된 최대 실행 시간을 가지며 cloudfare가 100 초를 갖는 것처럼 변경할 수 없습니다. 나는 대신 콘솔을 통해 실행되는 cron 작업을 만들어 해결했습니다. 그것을 고려해보고, 나는 또한 나의 대답을 업데이트 할 것이다. – Imaginaroom

    +1

    엔진을 InnoDB로 바꾸고 공격적인 인덱싱 전략을 사용하면 거의 모든 성능 문제를 해결할 수 있습니다. – fab

    관련 문제