Ecco un semplice esempio che mette in evidenza il pericolo di wites simultanei:
<?php
for($i = 0; $i < 100; $i++) {
$pid = pcntl_fork();
//only spawn more children if we're not a child ourselves
if(!$pid)
break;
}
$fh = fopen('test.txt', 'a');
//The following is a simple attempt to get multiple threads to start at the same time.
$until = round(ceil(time()/10.0) * 10);
echo "Sleeping until $until\n";
time_sleep_until($until);
$myPid = posix_getpid();
//create a line starting with pid, followed by 10,000 copies of
//a "random" char based on pid.
$line = $myPid . str_repeat(chr(ord('A')+$myPid%25), 10000) . "\n";
for($i = 0; $i < 1; $i++) {
fwrite($fh, $line);
}
fclose($fh);
echo "done\n";
Se le appende erano sicure, dovresti ottenere un file con 100 righe, di cui circa 10.000 caratteri lunghi e che inizia con un numero intero. E a volte, quando esegui questo script, è esattamente quello che otterrai. A volte, alcune appendici entrano in conflitto, e tuttavia si romperanno.
Si possono trovare le linee corrotte con grep '^[^0-9]' test.txt
Questo perché file append is only atomic if:
- si effettua una singola fwrite() chiamata
- e che fwrite() è più piccolo di PIPE_BUF (da qualche parte intorno 1 -4k)
- e si scrive su un filesystem completamente POSIX compatibile
Se si effettua più di una singola chiamata a fwrite durante l'append del log, o si scrive più di circa 4k, tutte le scommesse sono disattivate.
Ora, se questo è importante o meno: stai bene con alcune linee danneggiate nel tuo log sotto carico pesante? Onestamente, la maggior parte delle volte questo è perfettamente accettabile, ed è possibile evitare il sovraccarico del blocco dei file.
fonte
2010-03-02 02:07:51
+1. Ricevo voci sovrapposte nel mio registro di accesso di Apache ogni giorno, quindi a carico elevato si verifica sicuramente una certa perdita. Ma per un file di registro, le poche righe che vengono storpiate non contano, e certamente non valgono il sovraccarico del blocco dei file. –
@Laimoncijus, vuoi dire che gli appendi sono atomici? – Pacerier