meteorlake
@meteorlake
Кодю код, админю домашний сервер с фильмами

Почему один запущенный процесс php влияет на второй?

Вопрос: как первый запущенный скрипт не даёт произвести INSERT в базу второму?

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

В базе из нужного для этого процесса есть id(autoincrement) и status, по дефолту при добавлении status = 0

Код, который определит момент, когда можно начинать работать выглядит так:
Вносится запись нового процесса
Берётся его ID
Если в базе есть процесс с меньшим ID и статусом 1, то ждётся 1 секунда
Если в базе нет таковых, то актуальному процессу назначается статус 1

mysqli_query($GLOBALS["con"],"INSERT INTO `cronlog` (`type`) VALUES ('queue')");

$thisID = $GLOBALS["con"] -> insert_id;
$maxAttempts = 20;
While ($maxAttempts > 0) {
    // Есть ли старее ID со статусом 1?
    if ($GLOBALS["con"]->query("SELECT count(`id`) as exist FROM `cronlog` WHERE `status` = 1 AND `type` = '{$cronType}' AND `id` < $thisID")->fetch_assoc()['exist'] > 0) {
        // Если есть ждать 1 сек
        sleep(1);
    } else {
        // Если нет назначить статус
        mysqli_query($GLOBALS["con"],"UPDATE `cronlog` SET `status` = 1 WHERE `id` = $thisID");
        break;
    }
    $maxAttempts--;
}

if ($maxAttempts == 0) {
    // Если все попытки исчерпаны - выходим
    exit();
}


В свою очередь сама задача этого кода это цикл опрашивающий некоторые события (которых с примера я убрал) и после каждого цикла контролирующий нет ли нового процесса.

Если присутствует новый процесс с более высоким ID, то помечается статус 0 этому и закрывается скрипт
Если нет, то будет выжидание 1 секунды и перезапуск цикла.

While (1) {
    // Есть ID выше? - своему ID назначить статус 0 - exit
    if ($GLOBALS["con"]->query("SELECT count(`id`) as exist FROM `cronlog` WHERE `id` > $thisID AND `type` = '{$cronType}'")->fetch_assoc()['exist'] > 0) {
        mysqli_query($GLOBALS["con"],"UPDATE `cronlog` SET `status` = 0 WHERE `id` = $thisID");
        exit();
    } else {
        sleep (1); // Проблемный слип
    }
}


Но проблема в том, что если вот такой код запущу, то новый процесс не производит INSERT в базу данных и это занимает около 30 секунд, если слип убрать, то всё работает исправно.
  • Вопрос задан
  • 170 просмотров
Пригласить эксперта
Ответы на вопрос 1
Azurre
@Azurre
Web Developer
Вообще то такие вещи делаются через flock:
Добавляете в крон на постоянное выполнение и все. Она сам будет отслеживать, когда процесс умер и перезапускать его, без баз и приседаний:
flock -n /tmp/lockfile.lock /usr/bin/php worker.php

Если настроить завершение скрипта на 59 секунде простоя не будет вообще.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы