2009-07-30 19 views
19

Tengo dos archivos PHP diferentes que escriben en el mismo archivo. Cada script PHP es invocado por una acción del usuario de dos páginas HTML diferentes. Sé que será posible llamar a los dos archivos PHP, pero ¿intentarán ambos archivos PHP escribir en el archivo al mismo tiempo? Si es así, ¿qué pasará? Además, es posible hacer que uno de los PHP falle con elegancia (la escritura de archivos simplemente fallará, y el otro PHP puede escribir en el archivo) ya que una función de PHP es menos importante que la otra.PHP Simultaneous File Writes

Respuesta

28

La forma habitual de hacer frente a esto es tener dos scripts utilizan para bloquear flock():

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

Esto hará que las secuencias de comandos para esperar el uno al otro que hacer con el archivo antes de escribir en él. Si lo desea, el guión "menos importante" puede hacer:

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

de manera que simplemente no va a hacer nada si encuentra que algo está ocupado con el archivo.

+0

Exactamente lo que estaba buscando! Eso fue muy fácil, debería haber revisado más la documentación de PHP. –

+0

Tenga cuidado al utilizar flock() ya que la función no es atómica. – arul

+0

Otro consejo para evitar que el contenido del archivo se vacíe en dos escrituras exactamente simultáneas. Eso me pasó mucho con una página popular con un contador de visitantes flatfile. La solución: añadí un retraso aleatorio de 20-80 ms antes de fwrite(), y eso solucionó el problema, incluso hasta la fecha con recuentos de visitantes mucho más altos. –

-4

FYI: Multitud sólo funciona en * nix y no está disponible en Windows

+2

De la documentación de PHP: "flock() le permite realizar un modelo simple de lector/escritor que se puede usar en prácticamente todas las plataformas (incluida la mayoría de los derivados de Unix e incluso Windows)". – cdmckay

+1

Si bien 'flock' como una llamada al sistema no está implementado en Windows, esto se abstrae en la función PHP' flock'. – Piskvor

+1

sí, hablé mal. Este es el error en el que estaba pensando cuando dije que no estaba disponible en Windows: http://bugs.php.net/bug.php?id = 39138 (el tiempo que lo necesitaba en un servidor local de desarrollo de Windows, me encontré con esto y lo he evitado en máquinas con Windows desde entonces). Mantenga la calma y continúe. – xentek

9

Tenga en cuenta:

A partir de PHP 5.3.2, el desbloqueo automático al gestor de recurso de cerrar el archivo fue eliminado . Desbloquear ahora siempre tiene que hacerse manualmente.

El código es compatible con versiones anteriores actualizado:

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

es decir, usted tiene que llamar rebaño (.., LOCK_UN) de forma explícita porque fclose() no lo hace más.

11

Tenga en cuenta que posix establece el acceso atómico si los archivos se abren como anexen. Esto significa que puede anexar al archivo con varios hilos y que las líneas no se corromperán.

Lo probé con una docena de hilos y cientos de miles de líneas. Ninguna de las líneas estaba corrupta.

Esto podría no funcionar con cadenas de más de 1kB ya que el tamaño de búfer podría exceder.

Esto también podría no funcionar en Windows que no sea compatible con posix.