许多客户尝试写入CSV文件

时间:2017-10-25 16:40:54

标签: php csv append fopen

使用以下代码:

<?php
...
if (isset($_POST['id']))
{
    $out = fopen('test.csv', 'a');
    fputcsv($out, array($_POST['id'], $uid, $time, $_POST['name']));
    fclose($out);
}
?>

如果许多客户端(例如平均每秒10或100次)同时连接服务器会发生什么?

是否存在失去一些客户的风险?输入(这没关系,在CPU 100%使用的情况下不是什么大不了,我更喜欢这个而不是崩溃服务器),或者更糟,打开/关闭/打开/关闭/打开/关闭(两次)同时)擦除文件,从而导致过去的数据丢失

它仅用于简单的日志记录,我想避免为此设置MySql服务器。

1 个答案:

答案 0 :(得分:1)

如果附加到文件的数据大小太大,则可能会丢失数据。

如果附加数据的大小小于一定数量,则POSIX追加是原子的(意味着它们将启动并完成而不会被另一个进程覆盖)。在Linux上,这是4012字节。当进程尝试写入超过4012个字节时,它可能会覆盖正在尝试写入文件的任何进程。

如果您可以保证所有数据的组合(加上CSV所需的逗号,引号和换行符)每个条目的总和少于4012个字节,那么您就可以了。这意味着您需要进行严格的数据验证。

您可以通过使用flock()锁定文件来确保不会覆盖,这样一次只能写入一个进程:

$out = fopen('test.csv', 'a');

$tries = 5;
while ($tries > 0) {
    $locked = flock($out,LOCK_EX | LOCK_NB);
    if (! $locked) {
        usleep(10000);
        $tries--;
    } else {
        $tries = 0;
    }
}

if ($locked) {
    // If you got the lock, write and unlock.
    fputcsv($out, array($_POST['id'], $uid, $time, $_POST['name']));
    flock($out,LOCK_UN);
} else {
    // Do whatever if you didn't get the lock.
}

fclose($out);