mysql — блокировка PHP не работает. Не могу понять, почему

Привет, ребята, я следую за своим вопросом Acquire_lock () не работает. Бот по-прежнему отправляет запросы быстро. PHP + AJAX на который я не смог получить ответ.

Я упростила все и у меня есть три файла

  • abc.txt
  • file1.php
  • file2.php

Все в одном каталоге и содержимое обоих файлов php одинаково:

<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX|LOCK_NB)) {
print "No problems, I got the lock, now I'm going to sit on it.";
while (true)
sleep(5);
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>

Тем не менее, когда я загружаю любой из них, я получаю второе печатное сообщение: «Не совсем получил блокировку. Выходим сейчас. Спокойной ночи».

У кого-нибудь есть идеи, либо к этому вопросу, либо к тому, что происходит? Буквально в моем уме это заканчивается.

Спасибо как всегда.

0

Решение

Если вы хотите, чтобы php-скрипт не завершался, вам нужна блокирующая блокировка.

стадо Документация говорит, что вы можете сделать это, указав третий параметр. Также удаление LOCK_NB может помочь.

<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX, 1)) {
print "No problems, I got the lock, now I'm going to sit on it.";
// wait for 5 seconds
sleep(5);
// Release the lock now so that next script is executed
flock($x , LOCK_UN);
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>
0

Другие решения

Вот что происходит в вашем сценарии:

1) Ваш код входит в бесконечный цикл while(true) и он никогда не достигает оператора fclose () в конце.

2) Я проверил оба файла на моем локальном сервере: File1.php продолжал цикл, в то время как второй file2.php дал файлу сообщение о том, что файл заблокирован, и немедленно отправил сообщение (что означает, что первый файл заблокирован правильно). После этого я попытался обновить оба файла, и они оба не прошли тест блокировки.

Если вы используете PHP> 5.3.2, вам нужно разблокировать файл вручную:

Автоматическая разблокировка при закрытии дескриптора ресурса файла была
удален. Разблокировка теперь всегда должна выполняться вручную.
Источник

Если вы используете более старую версию PHP, то сценарий разблокирует файл после завершения выполнения сценария, так как вы входите в бесконечный цикл, сценарий никогда не выполняется и, следовательно, файл никогда не разблокируется.

Кроме того, даже если вы остановите запуск сценария в окне браузера, процесс php-cgi.exe, связанный с этим сценарием, останется запущенным и должен быть остановлен вручную из диспетчера задач (я сам это подтвердил)

Решение:

1)
Чтобы устранить эту проблему и заставить скрипт ждать блокировки, необходимо сначала убедиться, что скрипт действительно корректно останавливается, удалив бесконечный цикл:

Вот скрипт, который блокирует файл на 30 секунд (петля удалена):

<?php
$x = fopen("/var/www/abc.txt", "w");
if (flock($x, LOCK_EX|LOCK_NB)) {
print "No problems, I got the lock, now I'm going to sit on it.";
sleep(30);
fclose($x); // it is good practice to always close even your PHP <5.3.2
}
else {
print "Didn't quite get the lock. Quitting now. Good night.";
}

?>

2) Если вы используете Linux, вы можете использовать флаг LOCK_NB, чтобы определить, заблокирован файл или нет. Использование LOCK_NB должно быть таким:

while ( ! flock($f, LOCK_NB) )
{
sleep(1);
}

это заставит скрипт каждую секунду проверять блокировку и ждать окончания работы другого скрипта.

3) использовать flock($fp, LOCK_UN) явно снять блокировку, когда вы закончите вместо fclose ();
Таким образом, ваш код должен выглядеть так:

<?php
$x = fopen("/var/www/abc.txt", "w");
while(!flock($x,LOCK_NB)
sleep(1);

if (flock($x, LOCK_EX,true)) {
print "No problems, I got the lock, now I'm going to sit on it.";
sleep(30);
fflush($fp);            // flush output before releasing the lock
flock($fp, LOCK_UN);    // release the lock
} else {
print "Didn't quite get the lock. Quitting now. Good night.";
}
fclose($x);
?>
0