PHP одновременной записи файлов - PullRequest
20 голосов
/ 31 июля 2009

У меня есть два разных файла PHP, которые оба пишут в один и тот же файл. Каждый скрипт PHP вызывается действием пользователя двух разных страниц HTML. Я знаю, что будет возможно вызвать два PHP-файла, но будут ли оба PHP-файла пытаться записывать в файл одновременно? Если да, что будет? Кроме того, возможно изящное завершение одного из PHP (запись в файл просто не удастся, а другой PHP может записать в файл), поскольку одна функция PHP менее важна, чем другая.

Ответы [ 5 ]

31 голосов
/ 31 июля 2009

Обычный способ решения этой проблемы состоит в том, чтобы оба сценария использовали flock() для блокировки:

$f = fopen('some_file', 'a');
flock($f, LOCK_EX);
fwrite($f, "some_line\n");
flock($f, LOCK_UN);
fclose($f);

Это приведет к тому, что сценарии будут ждать, пока один файл не завершит работу, прежде чем записывать в него файл. Если хотите, «менее важный» скрипт может сделать:

$f = fopen('some_file', 'a');
if(flock($f, LOCK_EX | LOCK_NB)) {
    fwrite($f, "some_line\n");
    flock($f, LOCK_UN);
}
fclose($f);

, чтобы он ничего не делал, если обнаружил, что файл занят.

11 голосов
/ 21 января 2011

Обратите внимание, что posix заявляет атомарный доступ, если файлы открываются как append . Это означает, что вы можете просто добавить файл в несколько потоков, и они не будут повреждены.

Я проверил это с дюжиной нитей и несколькими сотнями тысяч строк. Ни одна из линий не была повреждена.

Это может не работать со строками размером более 1 КБ, поскольку размер буфера может превышать.

Это также может не работать на окнах, не поддерживающих posix.

9 голосов
/ 21 сентября 2010

Обратите внимание:

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

Обновлен обратно совместимый код:

if (($fp = fopen('locked_file', 'ab')) !== FALSE) {
    if (flock($fp, LOCK_EX) === TRUE) {
        fwrite($fp, "Write something here\n");
        flock($fp, LOCK_UN);
    }

    fclose($fp);
}

т.е. Вы должны вызывать flock (.., LOCK_UN) явно, потому что fclose () больше не делает этого.

1 голос
/ 31 июля 2009

Посмотрите на функцию flock .

0 голосов
/ 31 июля 2009

К вашему сведению: flock работает только на * nix и недоступно на Windows

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...