PHP и одновременный доступ к файлам - PullRequest
11 голосов
/ 16 ноября 2008

Я создаю небольшое веб-приложение на PHP, которое хранит некоторую информацию в виде простого текстового файла. Однако этот текстовый файл используется / изменяется всеми пользователями моего приложения в определенный момент времени и возможно одновременно.

Итак, вопросы есть. Как лучше всего убедиться, что только один пользователь может вносить изменения в файл в любой данный момент времени?

Ответы [ 4 ]

22 голосов
/ 16 ноября 2008

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

    $fp = fopen("/tmp/lock.txt", "r+");

if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    ftruncate($fp, 0);      // truncate file
    fwrite($fp, "Write something here\n");
    fflush($fp);            // flush output before releasing the lock
    flock($fp, LOCK_UN);    // release the lock
} else {
    echo "Couldn't get the lock!";
}

fclose($fp);

Взгляните на http://www.php.net/flock

11 голосов
/ 16 ноября 2008

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

3 голосов
/ 16 ноября 2008

Вы можете сделать что-то вроде формата журнала коммитов, как в Википедии.

Используйте базу данных, и каждое сохраненное изменение создает новую строку в базе данных, что делает предыдущую запись избыточной с инкрементным значением, тогда вам нужно только беспокоиться о получении блокировок таблицы на этапе сохранения.

Таким образом, по крайней мере, если 2 одновременно работающих пользователя что-то отредактируют, оба изменения появятся в истории, и все, что было проиграно в войне, может быть скопировано в новую ревизию.

Теперь, если вы не хотите использовать базу данных, вам нужно беспокоиться о том, чтобы файл контроля версий поддерживал каждый видимый файл.

Вы можете поместить контроль версий (GIT / MERCURIAL / SVN) в файловую систему, а затем автоматизировать фиксацию во время фазы сохранения,

Псевдокод:

 user->save : 
   getWritelock(); 
   write( $file ); 
   write_commitmessage( $commitmessagefile ); # <-- author , comment, etc 
   call "hg commit -l $commitmessagefile $file " ; 
   releaseWriteLock(); 
 done.

По крайней мере, так, когда 2 человека делают критические коммиты одновременно, ни один из них не потеряется.

2 голосов
/ 16 ноября 2008

Один файл для многих пользователей на самом деле не должен быть той стратегией, которую вы используете, я не думаю, иначе вам, вероятно, потребуется реализовать одну (глобальную) точку доступа, которая отслеживает, редактируется ли файл в настоящее время или нет , Получите блокировку, внесите изменения, снимите блокировку и т. Д. Я бы согласился с тем, что «никто не предлагает использовать базу данных (SQLite, если вы не хотите использовать накладные расходы для полностью удаленной СУБД)

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