PHP Одновременные записи файлов

19

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

    
задан Amandeep Grewal 31.07.2009 в 00:12
источник

5 ответов

29

Обычный способ обращения к этому состоит в том, чтобы оба сценария использовали 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);

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

    
ответ дан chaos 31.07.2009 в 00:15
источник
  • Именно то, что я искал! Это было так просто, я должен был проверить документацию PHP больше. –  Amandeep Grewal 31.07.2009 в 00:30
  • Постарайтесь использовать flock (), поскольку функция не является атомарной. –  arul 31.07.2009 в 00:42
  • Еще один совет, чтобы содержимое файла не становилось пустым на две точно одновременные записи. Это случилось со мной много с одной популярной страницей с помощью счетчика посещений с плоским файлом. Решение: я добавил случайную задержку в 20-80 мс до fwrite (), и это устранило проблему, даже на сегодняшний день, с гораздо большим количеством посетителей. –  Juha Untinen 30.01.2013 в 21:18
11

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

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

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

Это также может не работать в Windows, который не совместим с posix.

    
ответ дан anttir 21.01.2011 в 06:30
источник
9

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

  

Начиная с 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 () больше не делает этого.

    
ответ дан Marcello Nuccio 21.09.2010 в 10:06
источник
1

Посмотрите на ответ дан cdmckay 31.07.2009 в 00:15

источник
-4

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

    
ответ дан xentek 31.07.2009 в 01:39
источник
  • Из документации PHP: «flock () позволяет вам выполнить простую модель чтения / записи, которая может использоваться практически на каждой платформе (включая большинство производных Unix и даже Windows)». –  cdmckay 31.07.2009 в 02:45
  • В то время как стая как системный вызов не выполняется в Windows, это абстрагируется в функции стаи PHP. –  Piskvor 15.12.2010 в 18:25
  • да, я неправильно говорил. Это ошибка, о которой я думал, когда я сказал, что не был доступен в Windows: bugs.php.net/bug.php?id=39138 (время, которое мне было необходимо на локальном сервере-сервере Windows, я столкнулся с этим и с тех пор избегали его на машинах Windows). Сохраняйте спокойствие и продолжайте. –  xentek 09.01.2011 в 06:08