PHP кто профи чтения записи в файл? найдите ошибку

123 4
Ink-developer
На сайте с 31.01.2009
Offline
138
2672

Создаем 2 файла php с одинаковым кодом:


<?php
function write($dat){
$fopen=fopen("111.dat","a+");
flock($fopen,LOCK_EX); # Блокируем файл
$file=fread($fopen,50000000); /* Читаем 50 Mb из файла */
ftruncate($fopen,0); # Очищаем файл
if(strlen($file)>=1){ $file=explode("\n",$file); }else{ $file[0]=""; } # Если денные есть превращаем их в массив
$count=count($file);
if($count!="0"){ array_unshift($file,$dat); }else{ $file[0]=$dat; } # Если массив пустой создаем первый элемент иначе цепляем элемент в начало массива
$file=trim(implode("\n",$file)); # Массив превращаем в строку
fwrite($fopen,$file); # Записываем в файл
fflush($fopen);
flock($fopen,LOCK_UN); # Разблокируем
fclose($fopen); # Закрываем
}
for($kr=0;$kr<1000;$kr++){
write(time());
}
?>

Параллельно запускаем оба скрипта через браузер, суть в имитации многопоточной записи/чтения.

В итоге видим, что в файле не 2000-чи записей как хотелось бы, а рандом, обычно больше.

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

Где ошибка и в каком участке происходит сбой?

.

palladin_jedi
На сайте с 13.07.2010
Offline
71
#1
Ink-developer:
Параллельно запускаем оба скрипта через браузер, суть в имитации многопоточной записи/чтения.

Вот в этом участке ошибка. :)

Обычно такие процессы распараллеливают, чтобы они друг другу не мешали.

Сайт о web-разработке и прочем (http://seazo.net)||Продвижение статьями под Google (http://short.seazo.net/ght4zf) Бесплатные консультации рефералам Sape (http://www.sape.ru/r.SWfwWOblBo.php) PHP и JS скрипты на заказ, создание сайтов с нуля и на CMS.
gormarket
На сайте с 29.12.2010
Offline
47
#2

Ink-developer, попробуйте проверять возвращаемое функцией flock значение.

И еще flock может не всегда работать, посмотрите здесь например.

Товары и цены в магазинах Вашего города: Городской рынок (http://gormarket.ru/)
Ink-developer
На сайте с 31.01.2009
Offline
138
#3
palladin_jedi:
Вот в этом участке ошибка. :)
Обычно такие процессы распараллеливают, чтобы они друг другу не мешали.

Если это шутка, то прощаю, если вы серьезно, то молчу 😂

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

gormarket:
Ink-developer, попробуйте проверять возвращаемое функцией flock значение.

И еще flock может не всегда работать, посмотрите здесь например.

flock проверил файл блокируется, я только убедился что она блокирует файл и все.

.

palladin_jedi
На сайте с 13.07.2010
Offline
71
#4
Ink-developer:
Что значит, распараллеливают? как я могу распараллелить вызов скрипта двумя посетителями одновременно? То что я сделал 1000 циклов, этим я лишь увеличил вероятность запуска в один и тот-же момент (тоесть имитировал посещаемый сайт), любой другой скрипт не меняет ситуацию просто вероятность сбоя в разы меньше но она всегда есть.

Постараюсь объяснить:

Вы попытались сымитировать нагрузку большим файлом, который читается\пишется как минимум в 2 потока одновременно. Скрипты, к которым идёт обращение на сайте (тот же PHP) рассчитаны на быстрое выполнение - "исполнился и забыл", но никак не на параллельную, безошибочную, многопоточную запись в файл.

Короче, ладно, тут долго рассуждать можно...

Проверьте сначала статус файла на ваш LOCK_EX. Если заблокирован другим скриптом - не пишите. Попробуйте повторное обращение через интервал.

edogs software
На сайте с 15.12.2005
Offline
775
#5

ну а мануал-то на что писан?

http://ru2.php.net/flock

Returns TRUE on success or FALSE on failure.


$fp = fopen("/tmp/lock.txt", "r+");

if (flock($fp, LOCK_EX)) { // do an exclusive lock
ftruncate($fp, 0); // truncate file
fwrite($fp, "Write something here\n");
flock($fp, LOCK_UN); // release the lock
} else {
echo "Couldn't get the lock!";
}

fclose($fp);

Проверять надо (как в примере из мануала)- удачно Вы файл залочили или нет.

Если локнули неудачно, то надо снова пробовать залочить, а не ломиться сразу в него читать/писать.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
Ink-developer
На сайте с 31.01.2009
Offline
138
#6
palladin_jedi:
Скрипты, к которым идёт обращение на сайте (тот же PHP) рассчитаны на быстрое выполнение - "исполнился и забыл", но никак не на параллельную, безошибочную, многопоточную запись в файл.

Вы недопонимаете ситуацию, сейчас поясню:

Забываем про то, что писали выше и моделируем ситуацию по вашим правилам "быстрое выполнение - исполнился и забыл"

вот код


$fopen=fopen("111.dat","a+");
flock($fopen,LOCK_EX);
$file=fread($fopen,50000000);
if(strlen($file)>=1){ $file=explode("\n",$file); }else{ $file[0]=""; }
$count=count($file);
if($count!="0"){ array_unshift($file,$dat); }else{ $file[0]=$dat; }
$file=trim(implode("\n",$file));
ftruncate($fopen,0);
fwrite($fopen,$file);
fflush($fopen);
flock($fopen,LOCK_UN);
fclose($fopen);

Простейший быстрый скрипт, открыл записал закрыл, и что проблемы по вашему уже нет? Ни чего не изменилось, т.к. опять же заходят 2 пользователя в 1 единицу времени и косяк на лицо, а для того чтобы они вошли одновременно достаточно лишь высокой посещалки ресурса.

edogs:
Если локнули неудачно, то надо снова пробовать залочить

Первый стоящий ответ, ушел проверять.

palladin_jedi
На сайте с 13.07.2010
Offline
71
#7
Ink-developer:
Простейший быстрый скрипт, открыл записал закрыл, и что проблемы по вашему уже нет? Ни чего не изменилось, т.к. опять же заходят 2 пользователя в 1 единицу времени и косяк на лицо, а для того чтобы они вошли одновременно достаточно лишь высокой посещалки ресурса.

Вам выше я и edogs указали где у вас ошибка в логике скрипта.

Если не сложно, попытайтесь мне объяснить - что общего между высокой посещаемостью и чтением\записью довольно большого файла?

Ничего.

Ink-developer
На сайте с 31.01.2009
Offline
138
#8
palladin_jedi:

Вам выше я и edogs указали где у вас ошибка в логике скрипта.

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

palladin_jedi:
Если не сложно, попытайтесь мне объяснить - что общего между высокой посещаемостью и чтением\записью довольно большого файла?

В предыдущем скрипте не имеется ввиду что файл большой, там может быть хоть 2 строки по 10 символов, сбой все равно произойдет при совпадении времени обращения, посещаемость лишь увеличивает шансы, что скрипт будет вызван одновременно больше я этим ни чего не хотел сказать.

думаю ошибка расположена между:


flock($fopen,LOCK_EX); # Блокируем файл

где то тут

flock($fopen,LOCK_UN); # Разблокируем

может функция fread глючит? не полностью считывает файл.

BredoGen.
На сайте с 19.10.2009
Offline
98
#9

PHP. Defective by design.

dkameleon
На сайте с 09.12.2005
Offline
386
#10
On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!

Не ваш ли это случай?

Дизайн интерьера (http://balabukha.com/)
123 4

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий