Web - кодинг: PHP:
Как мы побороли flock
Автор: Дмитрий Смирнов
Источник:
Дано: файл, в который часто пишется информация и часто из
него считывается. Например, простой текстовый счетчик на страницу.
Проблема: рано или поздно, но обязательно случится ситуация, когда
одновременно к файлу будет несколько обращений — и на
запись и на чтение. И вся информация, натурально, потеряется.
Чтобы этого не случилось, существует специальный оператор
в PHP — . Который, по
идее, должен с этим бороться — сначала мы получаем эксклюзивные
права доступа к файлу, пишем туда, что хотим, а потом эти права
теряем.
В идеале это работает. Но — цитирую документацию по
PHP — «flock() will not work on NFS and many other networked file
systems. Check your operating system documentation for more details». Если
почитать все ту же документацию, то в комментариях пользователей
приводится множество способов побороть flock, вплоть до самых экзотичных.
Стоит ли говорить, что у меня ни сам flock, ни другие способы
просто не работали?
В конце концов, я набрел в одном англоязычном на интересную фразу как
раз по этому поводу: «A file rename operation is guaranteed to be
atomic by the operating system, and is very efficient as file functions
are always highly optimized».
То есть, rename — это атомарная, сиречь неделимая функция
операционной системы. К тому же она очень эффективная, потому
что файловые функции всегда хорошо оптимизированы.
Так что я попробовал побороть flock следующим образом: сначала
пишем все, что нам нужно, в временный файл (не забудьте выставить
правильный chmod на директорию, в которую он будет писаться),
а потом просто переименовываем этот файл в тот файл, который
нужно. Причем в unix-овых системах старый файл удалять
нет необходимости — все будет перезаписано сверху.
Я написал две функции. Первая функция — это функция записи
в файл, вторая — чтения из файла. Эти две функции интенсивно
работают у меня вот уже больше месяца, и пока не было ни одного
сбоя.
Запись в файл:
function S_fw ($COUNT_FILE, $text) { $z=rand
(0,100000); $fp = @fopen($COUNT_FILE.".".$z, "wb+");
@fwrite($fp,$text); @fclose($fp); if (@rename
($COUNT_FILE.".".$z, $COUNT_FILE)==false) { @unlink
($COUNT_FILE); @rename ($COUNT_FILE.".".$z,
$COUNT_FILE); } }
Чтение из файла (flock здесь стоит «на всякий случай»):
function S_fr ($COUNT_FILE) { clearstatcache(); $fp =
@fopen($COUNT_FILE, "rb"); @flock ($fp,LOCK_SH); $conts=@fread
($fp, filesize ($COUNT_FILE)); @fclose ($fp); @flock($fp,
LOCK_UN); return $conts; }
Пользуйтесь на здоровье.
PS. Мне тут подсказывают про . Использовать ее
будет более правильно, чем rand.
PSS. Прислали ссылку на , как
это можно сделать. Я не проверял.
При перепечатке любого материала
с сайта, видимая ссылка на источник www.warayg.narod.ru
и все имена, ссылки авторов обязательны.
© 2005
|