2009-07-30 21 views
19

Ho due diversi file PHP che scrivono entrambi nello stesso file. Ogni script PHP viene chiamato da un'azione dell'utente di due diverse pagine HTML. So che sarà possibile chiamare i due file PHP, ma entrambi i file PHP tenteranno di scrivere sul file nello stesso momento? Se sì, cosa accadrà? Inoltre, è possibile far fallire con grazia uno dei PHP (la scrittura del file fallirà e l'altro PHP può scrivere sul file) poiché una funzione PHP è meno importante dell'altro.Scrittura file simultanea PHP

risposta

28

Il solito modo di affrontare questo è di avere entrambi gli script utilizzano flock() per il bloccaggio:

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

Questo farà sì che gli script di attendere per l'altro per ottenere fatto con il file prima di scrivere ad esso. Se ti piace, lo script "meno importante" può fare:

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

in modo che semplicemente non fare nulla, se riconosce che qualcosa è occupato con il file.

+0

Esattamente quello che stavo cercando! È stato così facile, avrei dovuto controllare di più la documentazione PHP. –

+0

Fare attenzione all'utilizzo di flock() poiché la funzione non è atomica. – arul

+0

Un altro consiglio per evitare che il contenuto del file si svuoti su due scritture esattamente simultanee. Mi è successo molto con una pagina popolare con un contatore di visitatori flatfile. La soluzione: ho aggiunto un ritardo casuale di 20-80 ms prima di fwrite(), e questo ha risolto il problema, fino ad oggi con un numero di visitatori molto più alto. –

-4

FYI: Moltitudine funziona solo su * nix e non è disponibile su Windows

+2

Dalla documentazione di PHP: "flock() consente di eseguire un semplice modello di lettore/scrittore che può essere utilizzato praticamente su ogni piattaforma (inclusa la maggior parte dei derivati ​​Unix e persino di Windows)." – cdmckay

+1

Mentre 'flock' come una chiamata di sistema non è implementata su Windows, questo è astratto nella funzione PHP' flock'. – Piskvor

+1

sì, ho parlato male. Questo è l'errore a cui stavo pensando quando ho detto che non era disponibile su Windows: http://bugs.php.net/bug.php?id = 39138 (il tempo che mi serviva su un server di sviluppo locale di Windows, mi sono imbattuto in questo e l'ho evitato su macchine Windows da allora). Stai calmo e vai avanti. – xentek

9

Si prega di notare:

partire da PHP 5.3.2, lo sblocco automatico quando la maniglia risorse del file viene chiuso è stato rimosso . Lo sblocco ora deve sempre essere fatto manualmente.

Il codice compatibile aggiornato è:

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

cioè si deve chiamare gregge (.., LOCK_UN) in modo esplicito perché fclose() non lo fa più.

11

Nota posix indica l'accesso atomico se i file vengono aperti come append. Ciò significa che è possibile aggiungere al file diversi thread e che le linee non verranno danneggiate.

Ho provato questo con una dozzina di thread e poche centinaia di migliaia di righe. Nessuna delle linee era corrotta.

Questo potrebbe non funzionare con stringhe superiori a 1kB in quanto il buffer potrebbe superare.

Questo potrebbe non funzionare anche su Windows che non è conforme a posix.