Вопрос: как первый запущенный скрипт не даёт произвести 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 секунд, если слип убрать, то всё работает исправно.