关于PHP并行文件的读/写

时间:2014-08-21 01:02:49

标签: php

在网站上有一个文件。 PHP脚本会像这样修改它:

$contents   = file_get_contents("MyFile");

// ** Modify $contents **

// Now rewrite:
$file       = fopen("MyFile","w+");
fwrite($file, $contents);
fclose($file);

修改非常简单。它抓取文件的内容并添加几行。然后它会覆盖文件。

我知道PHP有一个函数可以将内容附加到文件而不是重写它。但是,我想继续使用这种方法,因为我可能会在将来更改修改算法(所以附加可能还不够)。

无论如何,我正在测试这个,做出100个请求。每次调用脚本时,我都会在文件中添加一个新行:


第一个电话:

  

首先!

第二个电话:

  

首先!

     

第二!

第三个电话:

  

首先!

     

第二!

     

第三!

非常酷。但那时:

第四个电话:

  

第四!

第五个电话:

  

第四!

     

第五!


如你所见,第一,第二和第三行完全消失了。

我已经确定问题不是内容字符串修改算法(我已单独测试过它)。在读取或写入文件时,有些东西搞砸了。

我认为问题很可能是在读取文件的内容时:如果由于某些奇怪的原因$contents为空,那么上面显示的行为是有意义的。

我不是PHP的专家,但也许我几乎同时执行100次调用的事实导致了这个问题。如果有两个进程,一个是写文件而另一个正在读取文件,该怎么办?

此问题的推荐方法是什么?当多个进程可以写/读同一个文件时,我该如何管理文件修改?

3 个答案:

答案 0 :(得分:3)

所以问题是对同一文件的并行访问,而另一个实例在文件更新之前正在读取文件。 PHP幸运地有一个锁定文件的机制,所以在释放锁并且文件已经更新之前,没有人可以读取它。

flock() 
可以使用

,文档为here

答案 1 :(得分:3)

您需要做的是使用flock()(文件锁定)

我认为正在发生的是你的脚本正在抓取文件,而前一个脚本仍在写入文件。由于文件仍然被写入,因此当PHP抓取它时它不存在,因此php获取一个空字符串,一旦后面的进程完成,它将覆盖以前的文件。

解决方案是在文件被锁定时让脚本usleep()持续几毫秒,然后再试一次。请务必限制脚本可以尝试的次数。

<强>注意:

如果另一个PHP脚本或应用程序访问该文件,则可能不一定使用/检查文件锁。这是因为文件锁通常被视为可选附加项,因为在大多数情况下它们不是必需的。

答案 2 :(得分:2)

您需要创建一个锁,以便任何并发请求都必须等待轮到他们。这可以使用flock()函数完成。您必须使用fopen(),而不是file_get_contents(),但这不应该是一个问题:

$file = 'file.txt';
$fh = fopen($file, 'r+');
if (flock($fh, LOCK_EX)) { // Get an exclusive lock
    $data = fread($fh, filesize($file)); // Get the contents of file
    // Do something with data here...
    ftruncate($fh, 0); // Empty the file
    fwrite($fh, $newData); // Write new data to file
    fclose($fh); // Close handle and release lock
} else {
    die('Unable to get a lock on file: '.$file);
}