2009-07-30 65 views
19

我有两个不同的PHP文件,都写入同一个文件。每个PHP脚本都由两个不同HTML页面的用户操作调用。我知道可以调用两个PHP文件,但是两个PHP文件会同时尝试写入文件吗?如果是的话,会发生什么?另外,可以让一个PHP正常失败(文件写入失败,另一个PHP可以写入文件),因为一个PHP函数不如其他PHP函数重要。PHP同时文件写入

回答

28

解决这个问题的通常方法是有两个脚本使用flock()锁定:

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

这将导致脚本等待对方得到写入之前对文件进行。如果你喜欢,在“不太重要”的脚本可以这样做:

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

,这样,如果它发现的东西是忙于文件就只是没有做任何事情。

+0

正是我在找的东西!这很简单,我应该更多地检查PHP文档。 – 2009-07-30 22:30:46

+0

小心使用flock(),因为函数不是原子的。 – arul 2009-07-30 22:42:41

+0

另一个提示可以防止文件内容在两次完全同时写入时变空。一个带有flatfile访客计数器的热门页面发生在我身上。解决方案:我在fwrite()之前添加了一个20-80毫秒的随机延迟,并且解决了问题,甚至到目前为止访问者数量还是很高。 – 2013-01-30 20:18:48

-4

FYI:涌向仅适用于* nix中,而不是在Windows上使用

+2

来自PHP文档:“flock()允许你执行一个简单的读写器模型,它几乎可以在任何平台上使用(包括大多数Unix衍生工具,甚至Windows)。” – cdmckay 2009-07-31 00:45:25

+1

虽然'flock'作为一个系统调用并没有在Windows上实现,但它在'flock' PHP函数中被抽象出来。 – Piskvor 2010-12-15 17:25:37

+1

是的,我说错了。这是当我说Windows在不可用时我正在考虑的错误:http://bugs.php.net/bug.php?id = 39138(我需要它在Windows本地开发服务器上的时间,我遇到过这种情况,并从此避免在Windows机器上使用它)。保持冷静并进行。 – xentek 2011-01-09 05:08:10

9

请注意:

由于PHP 5.3.2,自动解锁当文件的资源句柄被关闭移除。 解锁现在总是需要手动完成。

更新的向后兼容的代码是:

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

即你要调用的羊群(..,LOCK_UN)明确,因为FCLOSE()不这样做了。

11

请注意如果文件打开为附加,posix声明原子访问。这意味着你可以用多个线程追加到文件中,它们的行不会被破坏。

我用十几个线程和几十万行测试了这个。没有一条线被破坏。

这可能不适用于大于1kB的字符串,因为缓冲区大小可能会超过。

这可能也不适用于不符合posix的窗口。