PHP-скрипт с тайм-аутом запроса MySQL

У меня проблемы с запуском скрипта PHP, который вставляет данные в MySQL. Я получаю ошибку " 504 Gateway Time-out nginx " Когда страница PHP застревает с этим таймаутом, в базу данных было введено 10,102 строки данных. Я планирую вставить 160000 строк в одну загрузку скрипта.

Я сделал свой код более эффективным, используя подготовленный оператор для SQL. SQL также настроен в этой структуре:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

Я прочитал тайм- ауты SO PHP-скрипта и Как предотвратить тайм-аут php-скрипта из-за длинного запроса MySQL

Я попытался добавить в начало моего кода, но, похоже, ничего не изменилось:

set_time_limit(0);
ignore_user_abort(1);

Может кто-нибудь показать мне данные, чтобы разделить набор данных на куски и для каждого блока данных вставляются?

Я покажу раздел кода, который вставляет в MySQL ниже

 // prepare and bind
$stmt = $link->prepare("INSERT INTO MyGuests (`eventID`,`location`,`date`,`barcode`,`runner`,`time`,`Run Points`,`Volunteer Points`,`Gender`, `Gender pos`) VALUES (?,?,?,?,?,?,?,?,?,?)");
$stmt->bind_param("isssssiisi", $eventID,$location,$date,$barcode,$runner,$time,$runpoints,$volpoints,$gender,$genderpos);

// set parameters and execute
for( $x=0; $x < count($array_runner); $x++ ){
    $eventID=null;
    $barcode=$array_barcode[$x];
    $runner=$array_runner[$x];
    $time=$array_time[$x];
    $runpoints=$array_score[$x];
    $volpoints=' ';
    $gender=$array_gender[$x];
    $genderpos=$array_gender_pos[$x];

    $stmt->execute();

}

$stmt->close();
$link->close();

Я новичок в работе с MySQL и ищу руководство по этой проблеме.

2 ответа

set_time_limit(0); сбрасывает счет, когда он выполняется. Это не меняет max_execution_time в php.ini так что для того, чтобы он имел какой-либо полезный эффект, вы должны запустить его в цикле.

 // prepare and bind
$stmt = $link->prepare("INSERT INTO MyGuests (`eventID`,`location`,`date`,`barcode`,`runner`,`time`,`Run Points`,`Volunteer Points`,`Gender`, `Gender pos`) VALUES (?,?,?,?,?,?,?,?,?,?)");
$stmt->bind_param("isssssiisi", $eventID,$location,$date,$barcode,$runner,$time,$runpoints,$volpoints,$gender,$genderpos);

// set parameters and execute
for( $x=0; $x < count($array_runner); $x++ ){
    $eventID=null;
    $barcode=$array_barcode[$x];
    $runner=$array_runner[$x];
    $time=$array_time[$x];
    $runpoints=$array_score[$x];
    $volpoints=' ';
    $gender=$array_gender[$x];
    $genderpos=$array_gender_pos[$x];

    $stmt->execute();

    // every 5000 times through the loop reset the timeout
    if ( $x % 5000 == 0 ) {
        set_time_limit(30);
    }
}

$stmt->close();
$link->close();

Конечно, вы можете поиграть со значением 5000, поэтому он выполняет сброс реже.

Из руководства:

При вызове set_time_limit() сбрасывает счетчик тайм-аута с нуля. Другими словами, если время ожидания составляет 30 секунд по умолчанию и 25 секунд на выполнение сценария выполняется вызов, такой как set_time_limit(20), сценарий будет работать в общей сложности 45 секунд до истечения времени ожидания.

Если вы используете запрос внутри цикла с таким большим количеством строк, он наверняка застрянет.

Лучший способ, который я могу предложить, - это просто обработать все данные, которые нужно вставить в строку PHP, а затем запустить один запрос для вставки данных.

Позвольте мне уточнить

$data_to_insert = '' // will contain all data to inserted
$count = 1;
$eventID = null; // if it is null for all rows

for( $x=0; $x < count($array_runner); $x++ )
{    
    if($count == 1)  // checking if it is the first value to be inserted
    {
        $data_to_insert = "(";
        $count = 2;
    }
    else // with second value onwards
    {
        $data_to_insert = ",(" ;
    }

    $data_to_insert = $data_to_insert .   $eventID . ",";
    $data_to_insert = $data_to_insert . "'".   $barcode . "'";
    $data_to_insert = $data_to_insert . "'".   $array_runner[$x] . "'";
    $data_to_insert = ")";
}
// so in the last $data_to_insert should look like this
// $data_to_insert =  (eventid1 , 'barcode1', 'runner1'), (eventid2 , 'barcode2', 'runner2') and so on...

Затем запустите запрос

mysqli_query("INSERT INTO MyGuests (`eventID`,`barcode`,`runner`)  values" . $data_to_insert);
// which would look like
// INSERT INTO MyGuests (`eventID`,`barcode`,`runner`)  values (eventid1 , 'barcode1', 'runner1'), (eventid2 , 'barcode2', 'runner2')

Примечание: в моем коде может быть какая-то синтаксическая ошибка, но здесь вы понимаете логику.

Другие вопросы по тегам