2009-07-30 15 views
19

Mam dwa różne pliki PHP, które zapisują do tego samego pliku. Każdy skrypt PHP jest wywoływany przez akcję użytkownika dwóch różnych stron HTML. Wiem, że będzie możliwe wywoływanie dwóch plików PHP, ale czy oba pliki PHP spróbują jednocześnie pisać do pliku? Jeśli tak, co się stanie? Możliwe jest również, aby jeden z błędów PHP zawiódł (zapis pliku po prostu zawiedzie, a inny PHP może zapisać do pliku), ponieważ jedna funkcja PHP jest mniej ważna niż druga.Jednoczesne zapisywanie plików PHP

Odpowiedz

28

Zwykłym sposobem rozwiązania tego jest mieć oba skrypty używać flock() do blokowania:

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

Spowoduje skrypty czekać na siebie, aby zrobić z plikiem przed napisaniem do niego. Jeśli lubią, „mniej ważne” skrypt może zrobić:

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

tak, że nie tylko nic zrobić, jeżeli stwierdzi, że coś jest zajęty z pliku.

+0

Dokładnie to, czego szukałem! To było takie proste, powinienem był sprawdzić dokumentację PHP więcej. –

+0

Należy zachować ostrożność, używając funkcji flock(), ponieważ funkcja nie jest atomowa. – arul

+0

Kolejna wskazówka, aby zapobiec opróżnieniu zawartości pliku na dwóch dokładnie równoczesnych zapisach. Zdarzyło mi się to bardzo często na jednej popularnej stronie z licznikiem odwiedzanych plików. Rozwiązanie: Dodałem losowe opóźnienie 20-80 ms przed fwrite(), i to naprawiło problem, nawet do tej pory ze znacznie większą liczbą odwiedzających. –

-4

FYI: stada działa tylko na * nix i nie jest dostępna w systemie Windows

+2

Z dokumentacji PHP: "flock() pozwala na wykonanie prostego modelu czytnik/program piszący, który może być używany na praktycznie każdej platformie (włączając większość pochodnych Uniksa, a nawet Windows)." – cdmckay

+1

Podczas gdy 'flock' jako wywołanie systemowe nie jest zaimplementowane w systemie Windows, jest on wyodrębniany w funkcji PHP' flock'. – Piskvor

+1

Tak, źle mówiłem. To jest błąd, o którym myślałem, kiedy powiedziałem, że nie jest dostępny w systemie Windows: http://bugs.php.net/bug.php?id = 39138 (czas, którego potrzebowałem na lokalnym serwerze dev systemu Windows, natknąłem się na to i od tego czasu uniknąłem go na komputerach Windows). Zachowaj spokój i nie przerywaj. – xentek

9

Uwaga:

Od PHP 5.3.2, automatycznym odblokowaniem gdy uchwyt Resource plik jest zamknięta została usunięta . Odblokowanie teraz zawsze musi być wykonane ręcznie.

Zaktualizowana kod wstecznie kompatybilny jest:

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); 
} 

to trzeba zadzwonić flock (.., LOCK_UN) wyraźnie ponieważ fclose() nie robić tego więcej.

11

Należy pamiętać, że posix stwierdza dostęp atomowy, jeśli pliki są otwarte jako dołączyć. Oznacza to, że możesz po prostu dołączyć do pliku kilka wątków, a wiersze nie zostaną uszkodzone.

Zrobiłem to przy pomocy kilkunastu wątków i kilkuset tysięcy linii. Żadna z linii nie była uszkodzona.

Może nie działać z ciągami powyżej 1kB, ponieważ bufor może przekroczyć.

Może to również nie działać w systemie Windows, który nie jest zgodny z POSIX.

Powiązane problemy