Я тестирую свой код, используя небольшую базу данных в текстовых файлах. Самая важная проблема, которую я обнаружил: когда пользователи одновременно пишут в один файл. Для решения этой проблемы я использую flock
,
ОС моего компьютера — Windows с установленным xampp (прокомментируйте это, потому что я понимаю, что стаи отлично работают над Linux без окон) Однако мне нужно сделать этот тест на сервере Linux.
На самом деле я проверил свой код, загрузив один и тот же скрипт в 20 окон одновременно. Первые результаты работают нормально, но после теста файл базы данных кажется пустым.
Мой код:
$file_db=file("test.db");
$fd=fopen("".$db_name."","w");
if (flock($fd, LOCK_EX))
{
ftruncate($fd,0);
for ($i=0;$i<sizeof($file_db);$i++)
{
fputs($fd,"$file_db[$i]"."\n");
}
fflush($fd);
flock($fd, LOCK_UN);
fclose($fd);
}
else
{
print "Db Busy";
}
Как это возможно, что скрипт удаляет содержимое файла базы данных. Как правильно: использовать flock
с исправлением существующего кода или использовать другую альтернативную технику flock
?
Я переписал сценарий, используя ответ @ lolka_bolka, и он работает. Итак, в ответ на ваш вопрос, файл $db_name
может быть пустым, если файл test.db
пустой.
ftruncate
после fopen
с «ш» бесполезно.
file
функция
Возвращает файл в массиве. Каждый элемент массива соответствует строке в файле с новой строкой, все еще прикрепленной. В случае неудачи file () возвращает FALSE.
Вам не нужно добавлять дополнительный символ конца строки.
flock
функция
PHP поддерживает переносимый способ блокировки полных файлов консультативным способом (что означает, что все обращающиеся к нему программы должны использовать один и тот же способ блокировки, иначе он не будет работать).
Это означает, что file
функция не зависит от блокировки. Это означает, что $file_db=file("test.db");
мог читать файл, в то время как другой процесс где-то между ftruncate($fd,0);
а также fflush($fd);
, Итак, вам нужно прочитать содержимое файла внутри блокировки.
$db_name = "file.db";
$fd = fopen($db_name, "r+"); // w changed to r+ for getting file resource but not truncate it
if (flock($fd, LOCK_EX))
{
$file_db = file($db_name); // read file contents while lock obtained
ftruncate($fd, 0);
for ($i = 0; $i < sizeof($file_db); $i++)
{
fputs($fd, "$file_db[$i]");
}
fflush($fd);
flock($fd, LOCK_UN);
}
else
{
print "Db Busy";
}
fclose($fd); // fclose should be called anyway
Постскриптум вы можете протестировать этот скрипт с помощью консоли
$ for i in {1..20}; do php 'file.php' >> file.log 2>&1 & done