блокировка файлов в php - PullRequest
6 голосов
/ 27 марта 2011

У меня был новичок (ближайший подросток), написавший код php для отслеживания использования на моем веб-сайте.Я не знаком с php, поэтому я немного спрашиваю о параллельном доступе к файлам.

Мое родное приложение (в Windows) иногда регистрирует некоторые данные на моем сайте, нажимая на URL, содержащий мой php-скрипт.Собственное приложение не проверяет возвращенные данные.

        $fh = fopen($updateFile, 'a') or die("can't open file");
        fwrite($fh, $ip);
        fwrite($fh, ', ');
        fwrite($fh, $date);
        fwrite($fh, ', ');
        fwrite($fh, implode(', ', $_GET));
        fwrite($fh, "\r\n");
        fclose($fh);

Это сайт с низким трафиком, и данные не являются критическими.Но что произойдет, если два пользователя столкнутся и два экземпляра скрипта попытаются добавить строку в файл?Есть ли какая-либо неявная блокировка файлов в php?

Является ли приведенный выше код по крайней мере безопасным от блокировки и никогда не возвращает управление моему пользователю?Может ли файл быть поврежден?Если у меня есть сценарий, описанный выше, удаляйте файл каждый месяц, что произойдет, если другой экземпляр сценария находится в середине записи в файл?

Ответы [ 3 ]

12 голосов
/ 27 марта 2011

Вы должны поставить блокировку на файл:

<?php
$fp = fopen($updateFile, 'w+');
if(flock($fp, LOCK_EX)) {
fwrite($fp, 'a');
flock($fp, LOCK_UN);
} else {
echo 'can\'t lock';
}

fclose($fp);
3 голосов
/ 05 мая 2011

Поскольку это добавление к файлу, лучшим способом было бы объединить данные и записать их в файл в одной функции fwrite (), при условии, что записываемые данные не больше, чем файловый буфер. Конечно, вы не всегда знаете размер буфера, поэтому flock (); всегда хороший вариант.

2 голосов
/ 13 августа 2018

Для справки, я работал в библиотеке, которая делает это

https://github.com/EFTEC/DocumentStoreOne

Позволяет CRUD документы путем блокировки файла. Я попробовал 100 одновременных пользователей (100 обращений к PHP одновременно), и он держит.

Однако, он не использует flock, а mkdir

while (!@mkdir("file.lock")) {
   // use the file
   fopen("file"...)
   @rmdir("file.lock")
}

Почему?

  1. mkdir атомарен, поэтому блокировка атомарна: за один шаг ваш замок или нет.
  2. это быстрее, чем стадо (). Очевидно, что flock требует несколько обращений к файловой системе.
  3. стадо зависит от системы.
  4. Я провел стресс-тест, и он сработал.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...